我正在研究通过COM端口与另一台设备通信的项目.对于传入数据,我使用VaComm1RXchar事件,在那里我将消息存储到数组中并增加msgIndex,它表示消息数.
然后我调用我使用此消息的函数.
在这个函数内部是这个超时周期,我等待这个消息:
while MsgIndex < 1 do
begin
stop := GetTickCount;
if (stop - start)> timeout then
begin
MessageBox(0, 'Timeout komunikace !', 'Komunikace', MB_OK);
exit(false);
end;
sleep(10);
end;
Run Code Online (Sandbox Code Playgroud)
对我来说奇怪的是,当它像上面这样时,它总是以超时结束.但是当我在此之前放置一个ShowMessage('Waiting')然后它正确地工作.
有谁知道是什么原因造成的,我该如何解决?提前致谢!
我们可以推断出该VaComm1RXchar事件是一个同步事件,并且通过在循环中阻止您的程序,您正在阻止允许该事件执行的正常消息处理.
另一方面,显示模式对话框会将消息处理传递到该对话框,以便正确地处理消息队列和Rx事件并正常处理.
如果这也有效,你可以确定是这种情况(请不要写这样的代码 - 这只是为了证明这一点):
while MsgIndex < 1 do begin
stop := GetTickCount;
if (stop - start)> timeout then begin
MessageBox(0, 'Timeout komunikace !', 'Komunikace', MB_OK);
exit(false);
end;
Application.ProcessMessages; // service the message queue so that
sleep(10); // your Rx event can be handled
end;
Run Code Online (Sandbox Code Playgroud)
如果这里有一个教训,那就是需要在后台线程上完成RS-232通信."some chars have been received"由于您发现的原因,大多数事件的实现都会导致可怕的代码.您的主线程需要可以自由处理已收到字符的消息,但同时,您必须有一些并行进程等待接收到的字符才能完成一个有说服力的指令.在事件驱动程序中不存在合理的解决方案,以便在一个线程上同时管理用户界面和通信端口.
例如,AsyncPro**等一组组件将此功能包装到使用同步事件的数据包中,但组件管理工作线程上的开始和结束字符串(或字节)检测.这将从主线程中删除一级轮询(即:当完整数据包到达时,您总是会收到一个事件,而不是部分数据包).或者,您可以将通信工作移动到自定义线程并自行管理.
在任何一种情况下,这只是部分解决方案,当然,因为你仍然不能坚持在需要等待com流量的同步事件处理程序中编写长程序方法.如果您的单个过程需要对多个comport指令的序列做出反应,则第二级轮询(即管理一系列完整指令)仍然需要抽取消息队列.您还需要考虑的是将长方法分解为更短的部分,每个部分都响应特定的设备消息.
或者,对于严重程序化的流程自动化,将工作移动到后台线程通常也是一个好主意.这样,工作线程可以在等待来自硬件的事件时阻止同步对象(或在繁忙循环中轮询状态更新).一个线程可以管理低级别的comport流量,解析和中继这些命令或数据包,而另一个线程可以管理更高级别的进程,该进程正在处理构成更大进程的完整comport指令序列.主线程应该主要负责在工作者之间编组这些消息,而不是自己进行任何等待.
另请参阅:我不明白Delphi中的Application.ProcessMessages正在做什么
**VAComm也可能支持这样的事情,我不知道.API和文档不能从TMS for ASync32公开获取,因此您需要查阅当地文档.
| 归档时间: |
|
| 查看次数: |
433 次 |
| 最近记录: |