"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电脑上看到第二个线程发送的数据了
图中显示计算机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 调用是 SetCommMask
和 WaitCommEvent
。然后您可以使用 ClearCommError
来检测应该读取多少字节(因为接收事件不会告诉您接收到多少数据)。
您还可以使用重叠 IO 来允许同时 IO。我觉得它更干净,但并不简单。
我正在维护一个MFC程序,可以通过RS232将数据从计算机A发送到计算机B。有时它可以顺利传输数据,但有时它会永远挂起。有两个线程依次将相同的数据发送到 com 端口。第一个线程发送数据成功,但是第二个线程在代码"WriteFile"处挂起。当电脑A的第二个线程挂在"WriteFile"时,我从电脑B发送一些无意义的数据比如“1”回电脑A。然后电脑A在"WriteFile"的挂起停止,电脑B终于在A电脑上看到第二个线程发送的数据了
图中显示计算机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 调用是 SetCommMask
和 WaitCommEvent
。然后您可以使用 ClearCommError
来检测应该读取多少字节(因为接收事件不会告诉您接收到多少数据)。
您还可以使用重叠 IO 来允许同时 IO。我觉得它更干净,但并不简单。