gpt4 book ai didi

delphi - 为什么在 dll 内不调用 threadTerminate

转载 作者:行者123 更新时间:2023-12-03 14:47:34 24 4
gpt4 key购买 nike

我有一个问题,与正常应用程序中的相同代码相比,我的 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。

最佳答案

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

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

但是,如果它们不共享单个 RTL,那么它们将使用彼此不链接的单独 RTL 副本进行编译。默认情况下,EXE 中没有任何内容检查和处理来自 DLL 的 Synchronize() 的待处理请求。队列,仅来自 EXE 的 Synchronize()队列。为了解决这个问题,您必须从调用 CheckSynchronize() 的 DLL 中导出一个函数。 DLL 的 RTL 函数,然后定期(例如在计时器中)进行导出 DLL 函数的 EXE 调用。

否则,解决此问题的另一种方法是绕过 Synchronize()触发 OnTerminate 的调用事件,通过覆盖线程的虚拟 DoTerminate()方法(您不能使用 TThread.CreateAnonymousThread() 来执行此操作)。您可以拥有DoTerminate()调用OnTerminate直接,或者只是在 DoTerminate() 中执行您需要的操作本身。但无论哪种方式,您都必须确保此代码是线程安全的,如 DoTerminate()在工作线程的上下文中运行。

关于delphi - 为什么在 dll 内不调用 threadTerminate,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27954162/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com