我有一个用Delphi 2007编写的相当简单的多线程VCL gui应用程序。我在多个子线程(最多16个并发)中进行一些处理,需要更新主窗体上的网格控件(只需将字符串发布到a格)。没有一个子线程彼此交谈。
我的初始设计涉及调用TThread's "Synchronize"来更新当前运行的线程中的网格控件表单。但是,据我所知,调用Synchronize实际上就好像它是调用时的主线程一样。一次运行多达16个线程(大多数子线程的处理时间从<1秒到10秒),Window Messages是否会更好?
我已经让它在这一点工作,其中子线程发布一个Windows消息(由几个字符串的记录组成),主线程有一个监听器,只是在收到消息时更新网格。
在这种情况下对IPC的最佳方法有何看法?窗口消息或“同步”?
如果我使用窗口消息,您是否建议将代码包装在我在TCriticalSection(进入和离开)块中发布到网格的位置?或者我不需要担心线程安全,因为我在主线程中写入网格(虽然在窗口消息处理程序的函数内)?
答案 0 :(得分:36)
答案 1 :(得分:9)
顺便说一句,您也可以使用TThread.Queue()
代替TThread.Synchronize()
。 Queue()
是异步版本,它不会阻止调用线程:
(自{D8起,Queue
可用)。
我更喜欢Synchronize()
或Queue()
,因为它更容易理解(对于其他程序员)和更好的OO而不是简单的消息发送(无法控制它或能够调试它!)< / p>
答案 2 :(得分:5)
虽然我确信有正确的方法和错误的方式。我使用这两种方法编写代码,而我一直在返回的是SendMessage方法,我不知道为什么。
使用SendMessage vs Synchronize并没有什么区别。两者的工作基本相同。我认为我继续使用SendMessage的原因是我感觉到更多的控制,但我不知道。
SendMessage例程使调用线程暂停并等待,直到目标窗口完成处理发送的消息。因此,主要应用程序线程在调用期间基本上与调用子线程同步。您不需要在Windows消息处理程序中使用临界区。
数据传输本质上是从调用线程到主应用程序线程的一种方式。您可以在message.result中返回整数类型值,但不指向主线程中的内存对象。
由于两个线程是“同步”的,那个点和主应用程序线程当前被绑定响应SendMessage,那么你也不需要担心其他线程进入并同时丢弃你的数据时间。因此,您不必担心使用关键部分或其他类型的线程安全措施。
对于简单的事情,您可以定义单个消息(wm_threadmsg1)并使用wparam和lparam字段来回传输(整数)状态消息。对于更复杂的示例,您可以通过将其传递给lparam并将其转换回longint来传递字符串。 A-la longint(pchar(myvar))或使用pwidechar,如果您使用D2009或更新版本。
如果你已经使用了Synchronize方法,那么我就不用担心重做它来进行更改。