在Delphi中如何选择各种方式进行线程化? [英] How Do I Choose Between the Various Ways to do Threading in Delphi?

查看:164
本文介绍了在Delphi中如何选择各种方式进行线程化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

看来,我终于实现了一些线程到我的Delphi 2009程序。如果只有一种方法可以做到,我会跑下去。但是我看到几种可能性。



任何人都可以解释这些之间有什么区别,为什么我会选择一个。


  1. Delphi中的TThread类


  2. AsyncCalls Andreas Hausladen


  3. OmniThreadLibrary Primoz Gabrijelcic(gabr)


  4. ...任何其他? p>







编辑:



我刚刚阅读了Gabr在2010年3月(第10期)的 Blaise Pascal杂志

总而言之,Gabr描述了使用TThreads,直接的Windows API调用,Andy的AsyncCalls和他自己的OmniThreadLibrary。他最后得出结论:


我不是说你必须选择别的东西,而不是古典的Delphi方式(TThread )但是通知您有选项的情况仍然很好


Mghie的答案非常详尽,建议OmniThreadLibrary可能更为可取。但是我仍然对每个人对于我(或任何人)应该如何选择他们的线程方法的意见感兴趣。



您可以添加到列表中:



。 4.直接拨打Windows API



。 5. Misha Charrett的




结论:

>

我可能要和OmniThreadLibrary一起去。我喜欢加布尔的工作。我在几年前使用他的profiler GPProfile,而我正在使用他的GPStringHash,它实际上是OTL的一部分。



我唯一关心的是升级到64一旦Embarcadero将该功能添加到Delphi中,那么它们将被处理一次或者Unix / Mac处理。

解决方案

如果你没有多线程经验应该不会以 TThread 开头,因为它只是在本机线程上的薄层。我认为它也是围绕边缘有点粗糙的;自从Delphi 2引入以来,它并没有发展很多,主要是为了在Kylix时间框架中允许Linux兼容性进行更改,并纠正更明显的缺陷(如修复断开的MREW类,最后不推荐使用在最新的Delphi版本中暂停() Resume()



使用一个简单的线程封装类基本上也使得开发者关注的层次太低了。为了正确使用多个CPU内核,重点放在任务而不是线程上更好,因为使用线程的工作划分不能很好地适应不断变化的需求和环境,这取决于硬件和并行运行的其他软件的最佳数量线程可能会有很大变化,即使在同一系统的不同时间。一个你只传递大量工作的图书馆,并自动安排他们,以充分利用可用的资源有助于这方面的很多。



AsyncCalls是一个很好的将线程引入应用程序的第一步。如果程序中有几个区域需要执行相互独立的一些耗时的步骤,那么可以通过将它们分别传递给AsyncCalls来简单地执行它们。即使你只有一个这样的耗时的操作,你可以异步地执行它,只需在VCL线程中显示一个进度的UI,可以允许取消动作。



AsyncCalls IMO对于在整个程序运行期间保持环境的后台工作人员来说不是那么好,当程序中的某些对象具有线程关联性(例如可能需要所有调用的数据库连接或OLE对象)时,可能无法使用发生在同一个线程中)



您还需要注意的是,这些异步操作不是的火和 - 忘了每个重载的 AsyncCall()函数返回一个 IAsyncCall 接口指针,你可能需要保留引用,如果你想避免阻塞。如果不保留引用,那么当ref计数到零时,接口将被释放,这将导致线程释放接口等待异步调用完成。这是调试时可能会看到的,当退出创建 IAsyncCall 的方法可能需要一段神秘的时间。


$ b $在我看来,OTL在你看来是三种选择中最全面的,我不用第二个想法就可以使用它。它可以执行所有 TThread 和AsyncCalls可以做的事情,加上更多。它具有良好的声音设计,既能为用户提供便利,又能让Unixy系统的端口(尽可能保持大部分的接口)保持原有状态,如果不是很容易的话,这个设计很高。在最近几个月,它也开始获得一些高水平的平行工作结构,强烈推荐。



OTL也有几十个样本,这对于获取开始了AsyncCalls在注释中只有几行,但是由于功能有限(只做一件事情,但是做得很好),所以很容易理解。 TThread 只有一个样本,在14年内并没有真正改变,大部分是如何做不到的例子。



无论选择哪一个选项,都不需要了解线程基础知识。读了一本好书后,这是任何成功编码的先决条件。所有这些都是必需的。


It seems that I've finally got to implement some sort of threading into my Delphi 2009 program. If there were only one way to do it, I'd be off and running. But I see several possibilities.

Can anyone explain what's the difference between these and why I'd choose one over another.

  1. The TThread class in Delphi

  2. AsyncCalls by Andreas Hausladen

  3. OmniThreadLibrary by Primoz Gabrijelcic (gabr)

  4. ... any others?


Edit:

I have just read an excellent article by Gabr in the March 2010 (No 10) issue of Blaise Pascal Magazine titled "Four Ways to Create a Thread". You do have to subscribe to gain content to the magazine, so by copyright, I can't reproduce anything substantial about it here.

In summary, Gabr describes the difference between using TThreads, direct Windows API calls, Andy's AsyncCalls, and his own OmniThreadLibrary. He does conclude at the end that:

"I'm not saying that you have to choose anything else than the classical Delphi way (TThread) but it is still good to be informed of options you have"

Mghie's answer is very thorough and suggests OmniThreadLibrary may be preferable. But I'm still interested in everyone's opinions about how I (or anyone) should choose their threading method for their application.

And you can add to the list:

. 4. Direct calls to the Windows API

. 5. Misha Charrett's CSI Distributed Application Framework as suggested by LachlanG in his answer.


Conclusion:

I'm probably going to go with OmniThreadLibrary. I like Gabr's work. I used his profiler GPProfile many years ago, and I'm currently using his GPStringHash which is actually part of OTL.

My only concern might be upgrading it to work with 64-bit or Unix/Mac processing once Embarcadero adds that functionality into Delphi.

解决方案

If you are not experienced with multi-threading you should probably not start with TThread, as it is but a thin layer over native threading. I consider it also to be a little rough around the edges; it has not evolved a lot since the introduction with Delphi 2, mostly changes to allow for Linux compatibility in the Kylix time frame, and to correct the more obvious defects (like fixing the broken MREW class, and finally deprecating Suspend() and Resume() in the latest Delphi version).

Using a simple thread wrapper class basically also causes the developer to focus on a level that is much too low. To make proper use of multiple CPU cores a focus on tasks instead of threads is better, because the partitioning of work with threads does not adapt well to changing requirements and environments - depending on the hardware and the other software running in parallel the optimum number of threads may vary greatly, even at different times on the same system. A library that you pass only chunks of work to, and which schedules them automatically to make best use of the available resources helps a lot in this regard.

AsyncCalls is a good first step to introduce threads into an application. If you have several areas in your program where a number of time-consuming steps need to be performed that are independent of each other, then you can simply execute them asynchronously by passing each of them to AsyncCalls. Even when you have only one such time-consuming action you can execute it asynchronously and simply show a progress UI in the VCL thread, optionally allowing for cancelling the action.

AsyncCalls is IMO not so good for background workers that stay around during the whole program runtime, and it may be impossible to use when some of the objects in your program have thread affinity (like database connections or OLE objects that may have a requirement that all calls happen in the same thread).

What you also need to be aware of is that these asynchronous actions are not of the "fire-and-forget" kind. Every overloaded AsyncCall() function returns an IAsyncCall interface pointer that you may need to keep a reference to if you want to avoid blocking. If you don't keep a reference, then the moment the ref count reaches zero the interface will be freed, which will cause the thread releasing the interface to wait for the asynchronous call to complete. This is something that you might see while debugging, when exiting the method that created the IAsyncCall may take a mysterious amount of time.

OTL is in my opinion the most versatile of your three options, and I would use it without a second thought. It can do everything TThread and AsyncCalls can do, plus much more. It has a sound design, which is high-level enough both to make life for the user easy, and to let a port to a Unixy system (while keeping most of the interface intact) look at least possible, if not easy. In the last months it has also started to acquire some high-level constructs for parallel work, highly recommended.

OTL has a few dozen samples too, which is important to get started. AsyncCalls has nothing but a few lines in comments, but then it is easy enough to understand due to its limited functionality (it does only one thing, but it does it well). TThread has only one sample, which hasn't really changed in 14 years and is mostly an example of how not to do things.

Whichever of the options you choose, no library will eliminate the need to understand threading basics. Having read a good book on these is a prerequisite to any successful coding. Proper locking for example is a requirement with all of them.

这篇关于在Delphi中如何选择各种方式进行线程化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆