C++ &引用;Writefile“;对于使用MFC的RS232通信,将永远挂起,但是

C++ &引用;Writefile“;对于使用MFC的RS232通信,将永远挂起,但是,c++,mfc,serial-port,writefile,C++,Mfc,Serial Port,Writefile,我正在维护一个MFC程序,它可以通过RS232将数据从计算机a发送到计算机B。有时它可以顺利地传输数据,但有时它会永远挂起。有两个线程按顺序向com端口发送相同的数据。第一个线程成功发送数据,但第二个线程挂起在代码“WriteFile”处。当计算机A上的第二个线程挂起在“WriteFile”时,我将一些无意义的数据(如“1”)从计算机B发送回计算机A。然后计算机A上的“WriteFile”挂起停止挂起,计算机B最终看到计算机A上的第二个线程发送的数据 这是你的电话号码 图中显示,计算机A上的两

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

这是你的电话号码

图中显示,计算机A上的两个线程启动自己的测试并将消息发送回计算机B。每个线程几乎同时完成自己的测试并将完成的测试发送给计算机B。但是计算机B只能看到由计算机A上的第一个线程发送的测试(此时第二个线程挂在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”的可能原因是什么?为什么悬挂不会发生在一根线上?谢谢大家!

来自:

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

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

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


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

这可能与您的问题无关,但您使用的锁是错误的。
.Lock()
的要点是在锁未打开时等待;你不必自己等。第二次睡眠也是可疑的。对不起,我没有很好地解释这个功能。该函数将由多个线程调用,所有线程使用相同的RS232 com端口句柄。所以我使用lock来确保线程一次使用WriteFile。这并没有改变我的观点:你用错了。现在我明白了。“.Lock()”具有等待和查看锁是否未打开的两个函数。非常感谢。我应该修改代码,通过检查COMM事件来检查传入的RS232数据,而不是无休止地读取RS232。非常感谢你!