【问题标题】:"Writefile" for RS232 communication using MFC hangs forever, but使用 MFC 进行 RS232 通信的“Writefile”永远挂起,但是
【发布时间】:2016-10-30 13:13:45
【问题描述】:

我正在维护一个 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 上?谢谢!

【问题讨论】:

  • 这可能与您的问题无关,但您使用的锁错误。 .Lock() 的重点是在锁未打开时等待;你不必等待自己。第二次睡觉也很可疑。
  • 对不起,我没有很好地解释函数。该函数将被许多线程调用,并且所有线程都使用相同的 RS232 com 端口句柄。所以我使用锁来确保线程一次使用 WriteFile。
  • 这并没有改变我的观点:你用错了。不应该有任何 while() 或 Sleep()。
  • 现在我明白了。 “.Lock()”具有等待和查看锁是否未打开的两个功能。谢谢!

标签: c++ mfc serial-port writefile


【解决方案1】:

来自the MSDN page about serial communications

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

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

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

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

【讨论】:

  • 我应该修改我的代码,通过检查 COMM 事件来检查传入的 RS232 数据,而不是无休止地读取 RS232。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多