在TThread上创建主窗体

3

我有一个Delphi 2010应用程序,它导出一个DLL并拥有library头文件。它在TThread中创建了它的主窗体,代码如下:

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文件中,方法是在“选项” -> “应用程序”中更改生成的输出。并将标题从library更改为program,然后构建它并执行输出的EXE,而不是通过Windows API加载DLL,则在尝试创建窗体(特别是在Application.CreateForm(MyForm, form);处)时,应用程序会挂起。 如果我从线程中删除应用程序初始化并将其放置在主例程上,则它可以正常运行。
我正在尝试渲染的窗体只是一个空白窗体。有什么想法吗?
1个回答

4

当将此代码编译为一个程序时,在运行时,它将尝试在达到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.

另一方面,如果你试图在“程序”和“库”项目之间共享通用代码,那么你可以将“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.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接