gpt4 book ai didi

multithreading - 在单独的线程中运行 VCL

转载 作者:行者123 更新时间:2023-12-03 15:48:19 29 4
gpt4 key购买 nike

我现在遇到了一个相当罕见的情况。我有一个直接与 Windows 消息队列交互的应用程序。该应用程序还使用 LuaJIT 运行外部 Lua 脚本。我想要为这些脚本提供调试工具,因此我创建了一个普通的 VCL 应用程序,然后将其转换为 DLL 库。当第一个应用程序启动与库的调试 session 时,该 DLL 会创建一个单独的线程,整个 VCL 设施将在其中初始化并运行。

procedure TDebuggerThread.Execute;
begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm (TMainForm, MainForm);
Application.Run;
end;

VCL完全支持这种方式执行吗? TThread.Synchronize (Proc: TThreadProc) 将向哪个线程发送消息?

Inb4“发送给 VCL 和主应用程序的消息将会困惑” - 它们不会,因为每个线程都有自己的消息队列。

此外,您可能会看到来源 here 。 (也许)有问题的库名为 LuaDebugger。我目前正在使用 LuaDefaultHost 代替正确的客户端(CoreEngineClient),它是一个相当简单的控制台应用程序,调用调试器并表现得与 lua.exe 类似。使用控制台客户端,调试器工作得非常顺利 - 我遇到的唯一问题是,如果我在库仍在使用时关闭控制台窗口,VCL 会抛出“窗口处理程序不再有效”(俄语:/)。如果我让客户端按照预期的方式完成与调试器的交互,那么一切都会顺利。也许在单元终止期间调用 Windows.TerminateThread 应该可以解决这个问题。

最佳答案

您唯一的希望是创建线程,然后从该线程加载 DLL。因此,为了尽可能清楚,您创建线程,然后从该线程内执行的代码调用 LoadLibrary 来加载 DLL。

VCL 必须在加载 DLL 的线程之外运行。 VCL 初始化发生在 DLL 初始化期间,并确定哪个线程是 VCL 主线程。 VCL主线程是初始化VCL的线程,加载DLL的线程。

您可能必须对整个方法保持清醒的头脑,因为您将在一个进程中拥有两个 GUI 线程、两个消息泵。显示模态窗口需要禁用两个 GUI 线程上的窗口。

我无法确定这种通用方法(同一进程中的两个 GUI 线程,其中一个是 VCL 线程)是否有效,但从未这样做过。不过我认为它很有可能飞起来。

<小时/>

您还问了一个非常具体的问题:

To which thread will TThread.Synchronize (Proc: TThreadProc) send its message?

答案始终是初始化模块的线程。因此,对于可执行文件来说,这是进程的主线程。对于 DLL,初始化模块的线程是调用 LoadLibrary 的线程,执行对 DllMain 的初始调用的线程,执行 DLL 单元初始化代码的线程。这在 RTL/VCL 中称为模块的主线程。它是 ID 由 System.MainThreadID 给出的线程。

为了证明这一点,如果您不相信我的话,这里有一个小演示。

可执行文件

program DllThreading;

{$APPTYPE CONSOLE}

uses
Classes, Windows;

type
TMyThread = class(TThread)
protected
procedure Execute; override;
end;

procedure TMyThread.Execute;
var
lib: HMODULE;
proc: procedure; stdcall;
begin
lib := LoadLibrary('dll.dll');
proc := GetProcAddress(lib, 'foo');
proc();
Sleep(INFINITE);
end;

begin
Writeln('This is the process main thread: ', GetCurrentThreadId);
TMyThread.Create;
Readln;
end.

DLL

library Dll;

uses
Classes, Windows;

type
TMyThread = class(TThread)
private
procedure DoStuff;
protected
procedure Execute; override;
end;

procedure TMyThread.DoStuff;
begin
Writeln('This is the thread which executes synchronized methods in the DLL: ', GetCurrentThreadId);
end;

procedure TMyThread.Execute;
begin
Writeln('This is the thread created in the DLL: ', GetCurrentThreadId);
Synchronize(DoStuff);
end;

procedure foo; stdcall;
begin
TMyThread.Create;
CheckSynchronize(1000);
end;

exports
foo;

begin
Writeln('This is the initialization thread of the DLL: ', GetCurrentThreadId);
end.

输出

This is the process main thread: 2788This is the initialization thread of the DLL: 5752This is the thread created in the DLL: 6232This is the thread which executes synchronized methods in the DLL: 5752

关于multithreading - 在单独的线程中运行 VCL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18932060/

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