我有一个Delphi DLL,我想在我的应用程序内部加载一个线程(不止一个,准确地说)。 DLL只是创建一个对象,然后它使用它并销毁它。从这个角度来看,DLL代码是线程安全的。
但是如果我在一个线程中加载该DLL会发生什么? DLL仍然是线程安全的吗?关于加载DLL的线程,我应该知道什么?我已经看到VCL具有在创建线程时设置的IsMultThread属性,但是dll会得到关于此的通知,还是应该手动执行?
答案 0 :(得分:11)
最常见的陷阱是使用全局变量。只要您不使用任何全局变量(或正确地同步访问您使用的变量),您将对线程安全有很长的路要走。
例如,内存管理器使用 IsMultiThread
在单线程情况下进行优化。我个人认为这几天不值得优化,因为几乎所有有用的代码都有一些描述的线程。我只是在您的DLL开头将IsMultiThread
设置为True,例如在您的DLL .dpr文件的begin
/ end
块中,或者在您单元的一个初始化部分中,它们相同。
要直接回答您的问题,除非您在该DLL中创建线程,否则DLL中的IsMultiThread
实例将不会设置为true。由于您在EXE中创建了线程,因此需要在DLL中自行完成。
更一般地说,在不知道代码的线程安全性以及线程安全的实际含义的情况下,根本不可能对代码的线程安全性说太多。后一点可能听起来很奇怪,但我所指的是Eric Lippert着名的What is this thing you call "thread safe"?文章中讨论的问题。
答案 1 :(得分:4)
将IsMultiThread
设置为True
库项目主要块中的第一件事:
library MyLibrary;
begin
IsMultiThread := True;
...
end.
这将指示内存管理器使用线程安全的分配/释放例程。
答案 2 :(得分:2)
如果你在线程中做什么都很小心,你会没事的。如果您需要更新主线程的VCL,请使用synchronize,或者更好,但不要。
我有一个很大的DLL,我在那里进行大量的数据库访问,并且它在一个线程中运行。在我的单元测试中,一切都运行得很好,但是当在主应用程序中的一个线程中运行时,它会高高飘扬。事实证明,我不得不重新阅读有关线程安全的数据库文档。在我的例子中,它是DBISAM,我只需要确保为线程数据库实例创建一个新会话,因此它不会与主要实例冲突。
我遇到麻烦的另一个地方(再次,在单元测试中工作得很好,在线程中失败)是使用XML处理。我必须在使用XML DOM之前/之后调用CoInitialize / CoUnInitialize。这适用于任何SOAP内容,它使用XML DOM。