multithreading - 在 TThread 上创建 MainForm

标签 multithreading delphi dll delphi-2010 tthread

我有一个导出 DLL 并具有 library header 的 Delphi 2010 应用程序。它在 TThread 中创建其 MainForm,如下所示:

var
  ActiveThread: TActive;
  
type
  TActive= class(TThread)
  protected
    procedure Execute; override;
  end;

procedure TActive.Execute;
begin
      Application.Initialize;
      Application.CreateForm(MyForm, form);
      Application.Run;
end;

begin
  ActiveThread := TActive.Create(true);
  ActiveThread.FreeOnTerminate := true;
  ActiveThread.Resume;
end.

每当我通过 LoadLibrary 函数加载这个 DLL 时,应用程序运行良好。 (显然它使用我传递给 LoadLibrary 的线程作为主线程并且没有任何问题)

但是如果我尝试通过在选项 -> 应用程序中更改生成的输出来将此 DLL 导出到实际的 EXE。并将 header 从 library 更改为 program 然后构建它并执行输出 EXE 而不是通过 windows api 加载 DLL,应用程序在尝试创建表单时挂起,特别是在 Application.CreateForm(MyForm, form);。如果我从线程中删除应用程序初始化并将其放在主例程中,它运行得很好。

我要呈现的表单只是一个空表单。有什么想法吗?

最佳答案

将此代码编译为程序时,在运行时它将尝试在到达end. 时自行终止,甚至在工作线程有机会运行之前,这可能(并且很可能)发生在 Application 对象被销毁之后。在让程序退出之前,您必须等待工作线程完成其工作,例如:

program MyProgram;

uses
  Classes, Forms, MyForm;

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

procedure TActive.Execute;
begin
  Application.Initialize;
  Application.CreateForm(TMyForm, MyForm);
  Application.Run;
end;

var
  ActiveThread: TActive;
begin
  ActiveThread := TActive.Create(False);
  ActiveThread.WaitFor;
  ActiveThread.Free;
end.

但是,确实没有充分的理由像这样使用工作线程,这违背了使用线程的全部目的,因此您还不如完全摆脱它:

program MyProgram;

uses
  Forms, MyForm;

begin
  Application.Initialize;
  Application.CreateForm(TMyForm, MyForm);
  Application.Run;
end.

另一方面,如果您试图在programlibrary 项目之间共享公共(public)代码,那么您可以包装Application 代码在函数内部并让项目决定哪个线程调用该函数,例如:

unit MyApp;

interface

procedure RunMyApp;

implementation

uses
  Forms, MyForm;

procedure RunMyApp;
begin
  Application.Initialize;
  Application.CreateForm(TMyForm, MyForm);
  Application.Run;
end;

end.
program MyProgram;

uses
  MyApp;

begin
  RunMyApp;
end.
library MyLibrary

uses
  Classes, MyApp;
  
type
  TActive = class(TThread)
  protected
    procedure Execute; override;
  end;

procedure TActive.Execute;
begin
  RunMyApp;
end;

var
  ActiveThread: TActive;
begin
  ActiveThread := TActive.Create(True);
  ActiveThread.FreeOnTerminate := True;
  ActiveThread.Resume;
end.

关于multithreading - 在 TThread 上创建 MainForm,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66251082/

相关文章:

java - 将 Java 套接字从线程 A 传递到 B

c++ - 在 Win32 上如何将线程移动到另一个 CPU 核心?

java - 我怎样才能永远在Android应用程序中保留一个线程?

delphi - 在 Delphi 中修改 Rest 服务器上的 URL

android - 如何在 Android 上找到传递给 Delphi 应用程序的文件?

c# - 在 Visual Studio 命令提示符 2010 中构建 c# dll 时如何指定 .net 目标框架?

c# - 通过事件进行线程更新主屏幕

delphi - 如何访问记录属性?

c++ - 系统错误 - "the code cannot proceed because .dll was not found."

c++ - 声明 HMODULE 会在运行时抛出异常