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

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

本文关键字:永远 挂起 Writefile 使用 RS232 通信 MFC      更新时间:2023-10-16

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

这是来自计算机B的RS232日志.

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

这是我的代码发送信息从计算机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上发生?谢谢你!

来自MSDN关于串行通信的页面:

如果一个线程阻塞等待它的I/O操作完成,随后调用通信API的所有其他线程都将是阻塞,直到原始操作完成。例如,如果一个线程正在等待ReadFile函数返回,任何其他发出WriteFile函数的线程将被阻塞。

您可能发出阻塞ReadFile,阻止WriteFile完成。在您的情况下,这将是线程之间的竞争条件;写操作通常在调用读操作之前完成,但也不总是这样。

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

你也可以使用重叠IO来允许同时IO。