我想在示例应用程序中有三个线程
线程#1(主线程) - 用户界面/ GUI
线程#2 - 绑定到通过传递到数据队列的事件接收数据的串行端口设备
线程#3 - 在创建队列条目时激活,处理数据节点,释放数据对象。
目标是
a)当鼠标悬挂在主表格上的按钮或表格时,防止数据丢失
b)快速从事件中获取数据,将其填入队列,然后重新进入睡眠状态
c)我们有数据处理数据,否则睡觉。
像AsyncoPro这样的软件包可以将事件处理绑定到非主线程吗?
我从未对串口事件驱动的应用程序做过多少工作,我使用的大部分内容都经过轮询,我想做一些测试。
答案 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, 马丁