我有一个问题,与普通应用程序中的相同代码相比,我的dll中的代码表现不同.经过一些调试后,我发现线程的OnTerminate永远不会在dll中调用.
type
TTest = class
private
public
procedure threadStart();
procedure threadEnd(Sender: TObject);
procedure lines(value: String);
end;
procedure TTest.threadStart();
var aThread : TThread;
begin
aThread :=
TThread.CreateAnonymousThread(
procedure
begin
lines('start')
end
);
aThread.FreeOnTerminate := True;
aThread.OnTerminate := self.threadEnd;
aThread.Start;
end;
procedure TTest.threadEnd;
begin
lines('end')
end;
procedure TTest.lines(value: String);
var MyText: TStringlist;
begin
MyText:= TStringlist.create;
MyText.Add(value);
MyText.SaveToFile('.\filename.txt');
MyText.Free
end;
Run Code Online (Sandbox Code Playgroud)
如果我从普通的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()
队列中处理.要解决这个问题,您必须从调用CheckSynchronize()
DLL的RTL函数的DLL中导出函数,然后定期进行导出DLL函数的EXE调用,例如在计时器中.
否则,解决此问题的另一种方法是通过覆盖线程的虚拟方法(您无法做到)来绕过Synchronize()
触发OnTerminate
事件的调用.你可以直接打电话,或者只做自己需要的事情.但无论哪种方式,您必须确保此代码是线程安全的,因为在工作线程的上下文中运行.DoTerminate()
TThread.CreateAnonymousThread()
DoTerminate()
OnTerminate
DoTerminate()
DoTerminate()
归档时间: |
|
查看次数: |
432 次 |
最近记录: |