Delphi DLL - 线程安全
我有一个 Delphi DLL,我想将它加载到我的应用程序中的一个线程(准确地说是多个线程)中。 DLL 只是创建一个对象,然后使用它并销毁它。从这个角度来看,DLL 代码是线程安全的。
但是如果我在线程中加载该 DLL 会发生什么? DLL 仍然是线程安全的吗?关于加载 DLL 的线程,我应该了解哪些信息?我已经看到 VCL 有 IsMultThread 属性,该属性是在我们创建线程时设置的,但是 dll 会收到通知吗?还是我应该手动执行此操作?
I have a Delphi DLL and I want to load it in my app inside a thread (more than one, to be exactly). The DLL just creates a object, then it uses it and destroys it. For that point of view, the DLL code is thread safe.
But what happens if I load that DLL in a thread? Is the DLL still going to be thread safe? What should I know about threads loading DLL? I have seen that the VCL has the IsMultThread property that is set when we create a thread, but will the dll get notified about that or should I do it manually?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
最常见的陷阱是使用全局变量。只要您不使用任何全局变量(或正确同步对您使用的变量的访问),您就离线程安全还有很长的路要走。
例如,内存管理器使用 IsMultiThread 在单线程情况下进行优化。就我个人而言,我认为现在这不是一个值得的优化,因为几乎所有有用的代码都有一些描述的线程。我只需在 DLL 的开头将
IsMultiThread
设置为 True,例如在 DLL .dpr 文件的begin
/end
块中,或者在您的单元的初始化部分之一中,这相当于同一件事。为了直接回答您的问题,除非您在该 DLL 中创建线程,否则 DLL 中的
IsMultiThread
实例不会设置为 true。由于您在 EXE 中创建线程,因此您需要在 DLL 中自行创建线程。更一般地说,如果不知道代码的线程安全性以及线程安全的实际含义,就不可能对代码的线程安全性进行太多讨论。后一点可能听起来很奇怪,但我指的是 Eric Lippert 著名的 您称之为“线程安全”的东西是什么? 文章。
The most common pitfall is use of global variables. So long as you don't use any global variables (or properly synchronise access to the ones you do use) you will be a long way towards thread safety.
IsMultiThread
is used by, for example, the memory manager to make optimisations in the single threaded case. Personally I don't feel this is a worthwhile optimisation these days since practically all useful code has threads of some description. I'd just setIsMultiThread
to True at the start of your DLL, e.g. in thebegin
/end
block of your DLL .dpr file, or in one of your unit's initialization sections which amounts to the same thing.To answer your question directly, the instance of
IsMultiThread
in your DLL will not be set true unless you create a thread in that DLL. Since you create the threads in your EXE you need to do it yourself in the DLL.More generally, it's simply impossible to say much about thread safety of your code without knowing what it does and what you actually mean by thread safe. The latter point may sound odd, but what I'm referring to is the issue discussed in Eric Lippert's famous What is this thing you call "thread safe"? article.
将
IsMultiThread
设置为True
是库项目主块中的第一件事:这将指示内存管理器使用线程安全的分配/释放例程。
Set
IsMultiThread
toTrue
the first thing in the main block of your library project:This will instruct the memory manager to use thread-safe allocation/deallocation routines.
如果你小心你在线程中所做的事情,你会没事的。如果您需要更新主线程的 VCL,请使用同步,或者最好不要使用。
我有一个很大的 DLL,我在其中进行大量数据库访问,并且它在线程中运行。在我的单元测试中,一切都运行得很好,但是当在主应用程序的线程中运行时,一切都变得非常糟糕。事实证明,我不得不重新阅读有关线程安全的数据库文档。就我而言,它是 DBISAM,我只需确保为线程数据库实例创建一个新会话,这样它就不会与主会话发生冲突。
我遇到麻烦的另一个地方(同样,在单元测试中工作得很好,在线程中失败)是 XML 处理。我必须在使用 XML DOM 内容之前/之后调用 CoInitialize/CoUnInitialize。这对于任何在底层使用 XML DOM 的 SOAP 内容都是如此。
If you are careful about what you do in the thread, you'll be ok. If you need to update the VCL of the main thread, use synchronize, or better yet, don't.
I have a big DLL where I do lots of database access, and it runs in a thread. Everything worked great in my unit tests, but blew up sky high when run within a thread in the main app. Turns out, I had to re-read the database docs on thread safety. In my case, it's DBISAM and I just had to be sure to create a new session for the threaded database instance, so it wouldn't collide with the main one.
Another place where I ran into trouble (again, worked great in unit tests, failed in threads) is with XML handling. I had to call CoInitialize/CoUnInitialize before/after using the XML DOM stuff. This holds true for any SOAP stuff, which uses the XML DOM under the hood.