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

Ric*_*ler 5 delphi events multithreading

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

目标是
a)当主窗体上的鼠标按住按钮或表格时,防止数据丢失.
b)快速从事件中获取数据,将其填入队列,重新进入休眠状态
c)处理数据时,否则进入休眠状态.

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

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

Mas*_*ler 6

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

  • Windows API的许多部分都是以某种形式的线程安全.*thread safe*没有单一含义.如果没有精确地表达你对术语的意思,说某些东西是或不是线程安全的是不精确的.准确地说,Windows GUI代码具有线程关联性.因此,所有接收窗口句柄的API调用都必须来自创建窗口的线程.从该单个规则遵循以下规则:应该从主应用程序线程执行对VCL组件的操作. (4认同)
  • @Mason AFAIK Windows API*是*线程安全的,除非在MSDN中记录相反的情况.特别是,自早期版本的Windows以来,所有GDI,文件,内存和转换过程都是线程安全的.它甚至是过程安全的:您可以将GDI消息从一个进程发送到另一个进程,而不会出现问题.VCL*的UI部分不是*线程安全的,而VCL*的大多数非UI相关部分是*线程安全的. (3认同)

Arn*_*hez 5

最简单的方法是定义一些用户消息,然后将其从子线程发送到主线程.

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

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

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

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

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

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


Mar*_*mes 1

当然,您可以通过某种方式做到这一点。自 D5 以来未使用过 Apro - 我的 Apro 不适用于我的 D2009(unicode/string/ANSIstring 问题),并且我有自己的串行类。大多数可用的串行组件都可以选择在 rx 线程或主 GUI 线程上触发 dataRx 事件 - 显然,在您的情况下,您应该选择 rx 线程(线程 #2)。将接收数据推入某个缓冲区类并将其推入生产者-消费者线程(线程 #3)。在那里处理它。如果您需要从那里进行 GUI 更新,请 PostMessage 引用 GUI 线程并在用户定义的消息处理程序过程中处理它。

完成这种事情加载一次-它会工作正常。

Rgds,马丁