CSerialPort,支援多執行緒、四種接收模式現象:Win98 發送資料失敗,Win2K 正常。
根因:m_WriteOverlapped.hEvent 未建立事件物件。
修復:
if (this->IsOverlapped()) {
this->m_hWriteEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
if (this->m_hCloseEvent == NULL) return FALSE;
this->m_WriteOverlapped.hEvent = this->m_hWriteEvent; // 關鍵:綁定事件
}
現象:查詢模式下 Write 呼叫不返回。
根因:發送前殘留中斷遮罩,導致等待永不觸發。
修復:移除發送前的 SetMask(dwStoredFlags) 呼叫。
現象:程式直接崩潰而非回傳失敗。
根因:CSerialPort::Open 拋出 CSerialException 未捕獲。
修復:
try {
this->m_pPort->Open(nPort, dwBaud, spParity, DataBits, spStopbits, spFC, m_IsOverlapped);
} catch (CSerialException* pE) {
pE->Delete();
return FALSE; // 優雅失敗
}
分析:EV_BREAK 等事件皆可由 AutoReceiveBySignal 涵蓋。
決定:暫保留相容性,標記棄用。
問題:依賴 CommTimeouts 導致定時接收不精準。
決定:暫保留,文件標註不推薦新專案使用。
| 問題 | 影響 | 狀態 |
|---|---|---|
| 流控制模式未驗證 | RTS/CTS、DTR/DSR 可能失效 | 待測試 |
封裝洩漏 GetSerialPort() | 使用者可繞過類別直接操作底層,破壞封裝 | 架構限制 |
| ManualReceiveByConst 受 Timeout 影響 | 定時精度不足 | 已棄用標記 |
| 單機單 COM 測試環境 | 短接 2/3 腳自測,真實多機環境未驗證 | 需實機測試 |
// 1. 定義回調
void OnReceiveData(LPVOID pSender, void* pBuf, DWORD InBufferCount) {
// 處理接收資料...
}
// 2. 開啟並註冊
m_ComPort.Open(2, LsComm::CComPort::AutoReceiveBySignal);
m_ComPort.SetReceiveFunc((FOnReceiveData)OnReceiveData, this);
// 3. 發送
char a[10000]; memset(a, 'a', sizeof(a));
m_ComPort.Output(a, sizeof(a));
OnComBreak 如何使用?
void OnComBreak(LPVOID pSender, DWORD dwMask, COMSTAT stat) {
switch (dwMask) {
case EV_BREAK: /* 處理中斷訊號 */ break;
case EV_CTS: /* 處理 CTS 變化 */ break;
// EV_DSR, EV_ERR, EV_RING, EV_RLSD...
}
}
m_ComPort.SetBreakHandleFunc(OnComBreak);
DataWaiting 與 Attach 無關?確認:DataWaiting 內部自行 SetMask(EV_RXCHAR) + WaitEvent,與 Attach 無關。但會暫時修改事件遮罩,併發場景需注意。
MSDN CreateFile 文件未限制,理論支援。實測建議仍優先用 Overlapped。
COMMTIMEOUTS 關係?ReadFile 受 SetCommTimeouts 控制,超時會觸發 hEvent。但 WaitForSingleObject(hEvent, timeout) 的 timeout 與 CommTimeouts 疊加,實際等待時間可能超出預期。
核心:CComPort 聚合 CSerialPort + CReadComThread,四種模式由執行緒 Execute 分派
「寫程式,就是要認真仔細地面對自己寫的每一行代碼,不放過自己的每一個 Bug。誰都希望自己的程式不出一個 Bug,可這實在是說起來容易做起來難。」
歡迎回報 Issue 至 Milo2002@sohu.com,有空持續迭代。