使用MFC进行RS232通信的“Writefile”永远挂起,但是

时间:2016-06-28 09:29:34

标签: c++ mfc serial-port writefile

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

这是RS232 log from computer B

图片显示计算机A上的两个线程启动自己的测试并将消息发送回计算机B.每个线程完成自己的测试并几乎同时向计算机B发送TEST_DONE。但计算机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上没有挂起?谢谢!

1 个答案:

答案 0 :(得分:1)

来自the MSDN page about serial communications

  

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

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

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

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