"Writefile" 使用 MFC 的 RS232 通信永远挂起,但是

"Writefile" for RS232 communication using MFC hangs forever, but

我正在维护一个MFC程序,可以通过RS232将数据从计算机A发送到计算机B。有时它可以顺利传输数据,但有时它会永远挂起。有两个线程依次将相同的数据发送到 com 端口。第一个线程发送数据成功,但是第二个线程在代码"WriteFile"处挂起。当电脑A的第二个线程挂在"WriteFile"时,我从电脑B发送一些无意义的数据比如“1”回电脑A。然后电脑A在"WriteFile"的挂起停止,电脑B终于在A电脑上看到第二个线程发送的数据了

这是RS232 log from computer B .

图中显示计算机A上的两个线程发起自己的测试并向计算机B发送回消息。每个线程完成自己的测试并几乎同时向计算机B发送TEST_DONE。但是计算机B只能看到计算机A上第一个线程发送的TEST_DONE(此时第二个线程挂在WriteFile上。)直到我手动将“1”从计算机B发送到计算机A。

这里是我的代码从电脑A发送消息到电脑B。cmd的长度是255。

BOOL SerialPort::AutoHandlerRES(unsigned char* cmd){
while(wait_transfer.IsLocked())
    Sleep(1000);
wait_transfer.Lock(); 
CString out;
BOOL RetB;
UCHAR EndChar[2]={0x0D,0x0A};
out=CString(cmd);
DWORD num = out.GetLength()+2;
cmd[num-2]=EndChar[0];
cmd[num-1]=EndChar[1];
RetB=WriteFile(this->m_hCom, cmd, num, &num, NULL);
Sleep(1000);
wait_transfer.Unlock(); 
return RetB;}

我的问题是导致线程 B 在 "WriteFile" 挂起的可能原因是什么?为什么挂起不会发生在线程 A 上?谢谢!

来自 the MSDN page about serial communications :

If one thread is blocked waiting for its I/O operation to complete, all other threads that subsequently call a communications API will be blocked until the original operation completes. For instance, if one thread were waiting for a ReadFile function to return, any other thread that issued a WriteFile function would be blocked.

您可能发出阻止 WriteFile 完成的阻塞 ReadFile。在您的情况下,这将是线程之间的竞争条件;写入通常在调用读取之前完成,但并非总是如此。

防止这种情况的最佳方法是不要粗心地调用 ReadFile,而是将其包装在与写入相同的锁中,并在读取之前等待接收 COMM 事件。原始 Win32 调用是 SetCommMaskWaitCommEvent。然后您可以使用 ClearCommError 来检测应该读取多少字节(因为接收事件不会告诉您接收到多少数据)。

您还可以使用重叠 IO 来允许同时 IO。我觉得它更干净,但并不简单。