【发布时间】:2013-09-26 17:51:54
【问题描述】:
我现在遇到了一种相当罕见的情况。 我有一个直接与 Windows 消息队列交互的应用程序。此应用程序还使用 LuaJIT 运行外部 Lua 脚本。我想为这些脚本提供调试工具,所以我创建了一个普通的 VCL 应用程序,然后将其转换为 DLL 库。当第一个应用程序启动与库的调试会话时,此 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。代替一个合适的客户端(Core,Engine,Client)我目前正在使用LuaDefaultHost,这是一个相当简单的控制台应用程序,调用调试器并且行为主要类似于lua.exe。
使用控制台客户端,调试器的工作出奇地顺利——我遇到的唯一问题是,如果我在仍然使用库时关闭控制台窗口,VCL 会抛出“窗口处理程序不再有效”(俄语:/)。如果我让客户端按照预期的方式完成与调试器的交互,那么一切都会顺利。可能在单元定稿期间调用Windows.TerminateThread 应该可以解决这个问题。
【问题讨论】:
-
要么我遗漏了一些东西,要么您正在访问和运行方法并在不同线程中创建的 Application 对象上运行消息队列。我认为它应该早点崩溃..
-
@SertacAkyuz 我也是这么想的。显然,VCL 比我们想象的更灵活。 :O 不过,我仍然没有尝试将库与 GUI 客户端一起使用,仅使用控制台客户端。可能我需要运行一个特殊的实验来确定 VCL 是否仍然以某种方式使用主线程的队列。
-
@Deligamer VCL 怎么能做到这一点? VCL 如何强制自己进入可执行文件拥有的线程?它不能通过武力做到这一点。它需要可执行文件的合作。 VCL 没有任何进程主线程的概念。只有 VCL 线程,即初始化 VCL 的线程。
-
@DavidHeffernan Units 的 initialization 代码在客户端线程中运行,
Application.*方法在调试器线程中运行。我假设单元初始化创建的资源未绑定到特定线程。看起来是这样,但我可能错了。之前你说过只有当我从一个新线程中调用LoadLibrary时它才会起作用;现在你说移动Application.Initialize是可以的。这是什么意思? -
我并没有说什么不同。初始化代码从 DllMain 运行。这决定了 VCL 线程。这就是调用 LoadLibrary 的线程,因为 DllMain 在调用 LoadLibrary 的线程中运行。因此,VCL 使用的线程是调用主机中的 LoadLibrary 的线程。你无法改变它。
标签: multithreading delphi c++builder vcl