首版發布後收到不少回饋,第二版進行大幅重構:完全遵循 Win32 命名規範、整合阻塞/非阻塞模式、修正 COM10 以上埠號無法開啟問題、修正執行緒結束邏輯錯誤,穩定性大幅提升。
Windows NT/2000 下開啟 COM10 需使用裝置命名空間前綴:
// 錯誤寫法
CreateFile("COM10", ...);
// 正確寫法
CreateFile("\\\\.\\COM10", ...); // 對應 \\.\COM10
cnComm MyComm1(false, 0); // 無監視執行緒,阻塞模式
cnComm MyComm2; // 預設:有監視執行緒,非阻塞模式
cnComm MyComm3(true); // 有監視執行緒,阻塞模式
讀寫程式碼不再因模式不同而重複撰寫。
原代碼以 ResetEvent 結束 WaitCommEvent 等待,實際應使用 SetEvent:
// 原錯誤代碼
::SetCommMask(_hCommHandle, 0);
::ResetEvent(_WaitOverlapped.hEvent); // 錯誤:ResetEvent 不會喚醒等待
// 修正後
::SetEvent(_WaitOverlapped.hEvent); // 正確:喚醒等待執行緒
#pragma warning(disable: 4530)
#pragma warning(disable: 4786)
#include
#include
using namespace std;
#include "cnComm.h"
class MyComm : public cnComm {
public:
virtual void OnReceive() {
char Buffer[256];
if (Read(Buffer, 256))
cout << "Receive Data Form " << _dwPort << " : " << Buffer << endl;
}
};
int main(int argc, char* argv[]) {
try {
cnComm Com1(false, 0); // 阻塞模式
MyComm Com2; // 繼承擴展,非阻塞模式
Com1.Open(1, 1200);
Com2.Open(2, 1200);
char Buffer[] = "test com";
Com1.Write(Buffer);
Sleep(300);
Com1.Close();
} catch (exception& e) {
cout << e.what() << endl;
}
return 0;
}
筆者單位超過 40-50 個序列埠同時運行無異常。歡迎持續回饋問題與建議。