你能在Delphi XE的二级线程中接收事件吗?

时间:2011-07-05 20:45:37

标签: multithreading delphi events

我想在示例应用程序中有三个线程 线程#1(主线程) - 用户界面/ GUI
线程#2 - 绑定到通过传递到数据队列的事件接收数据的串行端口设备 线程#3 - 在创建队列条目时激活,处理数据节点,释放数据对象。

目标是 a)当鼠标悬挂在主表格上的按钮或表格时,防止数据丢失 b)快速从事件中获取数据,将其填入队列,然后重新进入睡眠状态 c)我们有数据处理数据,否则睡觉。

像AsyncoPro这样的软件包可以将事件处理绑定到非主线程吗?

我从未对串口事件驱动的应用程序做过多少工作,我使用的大部分内容都经过轮询,我想做一些测试。

3 个答案:

答案 0 :(得分:6)

您绝对可以将事件处理与非主线程联系起来。你不能做的是将屏幕更新绑定到非主线程。 Windows API不是线程安全的,因此构建在Windows API之上的Delphi VCL也不是。但是你的设计基本上是一个好的,可行的想法;只需记住使用Synchronize的{​​{1}}或Queue方法将任何UI更新发送回主线程上执行。

答案 1 :(得分:5)

最简单的方法是定义一些user messages,然后将其从子线程发送到主线程。

它完全是线程安全的,甚至是过程安全的。

PostMessage()与主窗体的句柄一起使用。但是不要将此WM_USER+n消息广播到整个UI,因为您可能会混淆定义其自定义消息的VCL的某些部分。

如果要复制一些跨线程或进程的文本数据,可以看到WM_COPY_DATA。实际上,这比用于小消息的命名管道快得多,速度快。

对于用户界面,我发现有时候无状态实现是个好主意。也就是说,您不通过Synchronize()调用或GDI消息回调主线程,但您的主GUI线程有一个计时器,用于检查共享内存缓冲区是否有挂起的更新。这就是网络的工作方式,在实践中,它很容易使用:你不必编写任何回调,每个线程都是独立的,做自己的东西,并在必要时刷新。

但当然,解决方案取决于您的确切项目架构。

对于一个简单但经过验证的库,请参阅AsyncCalls,从Delphi 5到XE。对于IDE的最新版本(Delphi 2007及更高版本),请查看OmniThreadLibrary。通过使用这些库,您将确保您的软件实现不会破坏任何地方:多线程应用程序在大多数情况下按预期工作是非常常见的,然后,由于未知原因,进入无限循环。当然,它只发生在客户方面,而不是你的......如果你不想花费数小时调试你的程序,那就相信那些已知经过精心设计和调试的成熟库。

答案 2 :(得分:1)

当然,你可以这样或那样做。从D5开始没有使用Apro - 我的Apro不能用于我的D2009,(unicode / string / ANSIstring问题),&我有自己的连续课程。大多数可用的串行组件都可以选择在rx线程或主GUI线程上触发dataRx事件 - 显然在你的情况下你应该选择rx线程,(线程#2)。将rx数据推送到某个缓冲区类并将其推送到生产者 - 消费者线程(Thread#3)。在那里处理它。如果您需要从那里进行GUI更新,请PostMessage对GUI线程的引用,并在用户定义的消息处理程序中处理它。

完成这类东西加载次数 - 它会正常工作。

RGDS, 马丁