简体   繁体   English

Delphi DLL - 线程安全

[英]Delphi DLL - thread safe

I have a Delphi DLL and I want to load it in my app inside a thread (more than one, to be exactly). 我有一个Delphi DLL,我想在我的应用程序内部加载一个线程(不止一个,确切地说)。 The DLL just creates a object, then it uses it and destroys it. DLL只是创建一个对象,然后它使用它并销毁它。 For that point of view, the DLL code is thread safe. 从这个角度来看,DLL代码是线程安全的。

But what happens if I load that DLL in a thread? 但是如果我在一个线程中加载该DLL会发生什么? Is the DLL still going to be thread safe? DLL仍然是线程安全的吗? What should I know about threads loading DLL? 关于加载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? 我已经看到VCL具有在创建线程时设置的IsMultThread属性,但是dll会得到关于此的通知,还是应该手动执行?

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. 例如, IsMultiThread被内存管理器用于在单线程情况下进行优化。 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 set IsMultiThread to True at the start of your DLL, eg in the begin / end block of your DLL .dpr file, or in one of your unit's initialization sections which amounts to the same thing. 我只是在DLL的开头将IsMultiThread设置为True,例如在DLL .dpr文件的begin / end块中,或者在单元的一个初始化部分中,这相当于同样的事情。

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. 要直接回答您的问题,除非您在该DLL中创建一个线程,否则DLL中的IsMultiThread实例将不会设置为true。 Since you create the threads in your EXE you need to do it yourself in the DLL. 由于您在EXE中创建线程,因此需要在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"? 后一点可能听起来很奇怪,但我所指的是Eric Lippert所着名的问题, 你称之为“线程安全”的东西是什么? article. 文章。

Set IsMultiThread to True the first thing in the main block of your library project: IsMultiThread设置为True是库项目主块中的第一件事:

library MyLibrary;
begin
  IsMultiThread := True;
  ...
end.

This will instruct the memory manager to use thread-safe allocation/deallocation routines. 这将指示内存管理器使用线程安全的分配/释放例程。

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. 如果您需要更新主线程的VCL,请使用synchronize,或者更好,但不要。

I have a big DLL where I do lots of database access, and it runs in a thread. 我有一个很大的DLL,我在那里进行大量的数据库访问,并且它在一个线程中运行。 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. 在我的例子中,它是DBISAM,我只需要确保为线程数据库实例创建一个新会话,因此它不会与主要实例冲突。

Another place where I ran into trouble (again, worked great in unit tests, failed in threads) is with XML handling. 我遇到麻烦的另一个地方(再次,在单元测试中表现很好,在线程中失败)是使用XML处理。 I had to call CoInitialize/CoUnInitialize before/after using the XML DOM stuff. 我必须在使用XML DOM之前/之后调用CoInitialize / CoUnInitialize。 This holds true for any SOAP stuff, which uses the XML DOM under the hood. 这适用于任何SOAP内容,它使用XML DOM。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM