看来我终于要在我的Delphi 2009程序中实现某种类型的线程。如果只有一种方法可以做到,那我就开始运行了。但是我看到了几种可能性。
谁能解释这些之间的区别以及为什么我会选择一个而不是另一个。
编辑:
我刚刚读了Gabr在Blaise Pascal Magazine于2010年3月(第10期)上发表的一篇出色的文章,标题为“创建线程的四种方法”。您必须订阅才能获得该杂志的内容,因此,根据版权,我无法在此处复制任何实质性内容。
总之,Gabr描述了使用TThreads,直接Windows API调用,Andy的AsyncCalls和他自己的OmniThreadLibrary之间的区别。最后他确实得出以下结论:
Mghie的答案很彻底,并建议使用OmniThreadLibrary是更可取的。但是,我仍然对每个人对我(或任何人)应如何选择其应用程序的线程方法的观点感兴趣。
您可以添加到列表中:
。 4.直接调用Windows API
。 5.由LachlanG在他的答案中建议的Misha Charrett's CSI Distributed Application Framework。
结论:
我可能会与OmniThreadLibrary一起使用。我喜欢加布(Gabr)的作品。多年前,我使用了他的探查器GPProfile,现在使用的是他的GPStringHash,它实际上是OTL的一部分。
一旦Embarcadero将其功能添加到Delphi中,我唯一关心的可能就是将其升级以与64位或Unix/Mac处理一起使用。
最佳答案
如果您不熟悉多线程,则可能不应该从TThread
开始,因为Suspend()
只是 native 线程上的一薄层。我认为它的边缘也有些粗糙。自从Delphi 2引入以来,它并没有发展太多,主要是为了允许在Kylix时间范围内与Linux兼容,并纠正更明显的缺陷(例如修复损坏的MREW类,最后在最近的版本中弃用Resume()
和AsyncCall()
)而进行的更改Delphi版本)。
使用简单的线程包装器类基本上还会使开发人员将精力集中在太低的级别上。为了正确使用多个CPU内核,将重点放在任务而不是线程上会更好,因为使用线程进行工作分区不能很好地适应不断变化的需求和环境-取决于并行运行的硬件和其他软件的最佳数量。即使在同一系统上的不同时间,线程的变化也可能很大。在此方面,您仅将工作量传递给一个库,并对其进行自动调度以充分利用可用资源,该库将大有帮助。
AsyncCalls是将线程引入应用程序的一个很好的第一步。如果您的程序中有几个区域需要执行彼此独立的许多耗时步骤,则可以将它们中的每个传递给AsyncCalls来简单地异步执行它们。即使只有一个这样的耗时操作,您也可以异步执行它,并仅在VCL线程中显示进度UI,可以选择取消该操作。
AsyncCalls对于在整个程序运行期间停留的后台工作人员而言,IMO不太好,并且当程序中的某些对象具有线程亲缘关系(例如数据库连接或OLE对象可能要求所有对象都具有线程亲和力)时,可能无法使用AsyncCalls调用发生在同一线程中)。
您还需要注意的是,这些异步操作不是“即发即弃”类型的。每个重载的IAsyncCall
函数都返回一个IAsyncCall
接口(interface)指针,如果要避免阻塞,可能需要保留该引用。如果不保留引用,则当引用计数达到零时,接口(interface)将被释放,这将导致释放接口(interface)的线程等待异步调用完成。这是您在调试时可能会看到的内容,当退出创建TThread
的方法时可能会花费很多时间。
我认为OTL是您三种选择中功能最丰富的一种,我会不加思索地使用它。它可以完成TThread
和AsyncCalls可以做的一切,还有更多。它具有良好的声音设计,它的高级程度足以使用户的生活变得轻松,并且如果不容易的话,至少可以使到Unixy系统的端口(同时保持大多数接口(interface)完好无损)看起来是可能的。在过去的几个月中,它还开始获得一些用于并行工作的高级构造,强烈建议这样做。
OTL也有几十个样本,这对于入门非常重要。 AsyncCalls在注释中只有几行,但是由于其功能有限(它只做一件事,却做得很好),因此很容易理解。 ojit_code只有一个样本,这在14年内并没有真正改变,并且大部分是不做事的例子。
无论选择哪个选项,都没有库会消除对线程基础知识的了解。阅读有关这些方面的好书是任何成功编码的先决条件。例如,所有这些都要求正确锁定。