delphi – 为什么不在dll中调用threadTerminate

前端之家收集整理的这篇文章主要介绍了delphi – 为什么不在dll中调用threadTerminate前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个问题,与普通应用程序中的相同代码相比,我的dll中的代码表现不同.经过一些调试后,我发现线程的OnTerminate永远不会在dll中调用.
  1. type
  2. TTest = class
  3. private
  4. public
  5. procedure threadStart();
  6. procedure threadEnd(Sender: TObject);
  7. procedure lines(value: String);
  8. end;
  9.  
  10. procedure TTest.threadStart();
  11. var aThread : TThread;
  12. begin
  13. aThread :=
  14. TThread.CreateAnonymousThread(
  15. procedure
  16. begin
  17. lines('start')
  18. end
  19. );
  20. aThread.FreeOnTerminate := True;
  21. aThread.OnTerminate := self.threadEnd;
  22. aThread.Start;
  23. end;
  24.  
  25. procedure TTest.threadEnd;
  26. begin
  27. lines('end')
  28. end;
  29.  
  30. procedure TTest.lines(value: String);
  31. var MyText: TStringlist;
  32. begin
  33. MyText:= TStringlist.create;
  34. MyText.Add(value);
  35. MyText.SaveToFile('.\filename.txt');
  36. MyText.Free
  37. end;

如果我从普通的VLC Delphi应用程序运行此代码,我会在文本文件中结束.
如果我从dll运行相同的代码(将其加载到静态或动态到VLC应用程序),我开始在文本文件中.

我的问题:为什么?或者更好的问一下,我怎么能让我的dll以与我的VLC相同的方式行事.我正在使用的当前版本是XE7.

解决方法

TThread.OnTerminate事件在主UI线程的上下文中通过调用TThread.Synchronize()来触发,该调用将请求存储在主UI线程定期检查的队列中,在可用时执行挂起的请求.

如果在启用运行时软件包的情况下编译DLL和EXE,则它们共享RTL的单个副本(因此需要您使用应用程序部署rtl.bpl).当EXE检查RTL的Synchronize()队列时,它将看到来自EXE和DLL的挂起请求.

但是,如果它们不共享单个RTL,则它们将使用不相互链接的RTL的单独副本进行编译.默认情况下,EXE中没有任何内容可以检查和处理来自DLL的Synchronize()队列的挂起请求,只能来自EXE的Synchronize()队列.要解决这个问题,您必须从调用DLL的RTL的CheckSynchronize()函数的DLL中导出函数,然后定期进行导出DLL函数的EXE调用,例如在计时器中.

否则,解决此问题的另一种方法是通过重写线程的虚拟DoTerminate()方法(使用TThread.CreateAnonymousThread()无法做到)来绕过触发OnTerminate事件的Synchronize()调用.您可以直接使用DoTerminate()调用OnTerminate,或者只是在DoTerminate()内部执行您需要的操作.但无论哪种方式,您必须确保此代码是线程安全的,因为DoTerminate()在工作线程的上下文中运行.

猜你在找的Delphi相关文章