我有一个问题,与正常应用程序中的相同代码相比,我的 dll 中的代码的行为不同。经过一些调试后,我发现 dll 中从未调用线程的 OnTerminate。
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;
如果我从普通的 VLC Delphi 应用程序运行此代码,我会得到end在文本文件中。
如果我从 dll 运行相同的代码(将其静态或动态加载到 VLC 应用程序中),我得到start在文本文件中。
我的问题:为什么?或者更好地问,我怎样才能让我的 dll 的行为与我的 VLC 相同。我当前使用的版本是XE7。
The TThread.OnTerminate
事件是通过调用在主 UI 线程的上下文中触发的TThread.Synchronize()
,它将请求存储在主 UI 线程定期检查的队列中,并在可用时执行挂起的请求。
如果 DLL 和 EXE 是在启用运行时包的情况下编译的,则它们共享 RTL 的单个副本(因此需要您部署rtl.bpl
与您的应用程序)。当 EXE 检查 RTL 时Synchronize()
队列中,它将看到来自 EXE 和 DLL 的待处理请求。
但是,如果它们不共享单个 RTL,那么它们将使用彼此不链接的单独 RTL 副本进行编译。默认情况下,EXE 中没有任何内容检查和处理来自 DLL 的待处理请求。Synchronize()
队列,仅来自 EXESynchronize()
队列。为了解决这个问题,你必须从 DLL 中导出一个函数来调用CheckSynchronize()
DLL 的 RTL 函数,然后周期性地(例如在定时器中)导出 DLL 函数的 EXE 调用。
否则,解决此问题的另一种方法是绕过Synchronize()
调用触发OnTerminate
事件,通过覆盖线程的虚拟DoTerminate()
方法(你不能用TThread.CreateAnonymousThread()
)。你可以有DoTerminate()
call OnTerminate
直接,或者只是在里面做你需要的事情DoTerminate()
本身。但无论哪种方式,你都必须确保这段代码是线程安全的,因为DoTerminate()
在工作线程的上下文中运行。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)