Delphi 当线程正在等待事件时应用程序终止会发生什么情况?
Delphi What happens when the app terminates while a thread is waiting on an event?
我有一个线程通过事件循环执行工作和休眠一段时间(几秒钟)。用户可以在线程休眠等待事件时终止应用程序。在那种情况下,事件实际上发生了什么?线程是否保持 运行 直到事件超时,从而延迟应用程序的完全终止?还是 return 立即使用 return 值而不是超时?
虽然启动比创建它们的 Delphi 应用程序寿命更长的进程并非不可能,但以通常方式(通过 TThread.Create)创建和启动的线程会在主线程结束后立即结束,无需等待一个周期完成,也无需阻止主应用程序的终止。
要让自己相信这一点,请创建一个 Delphi 应用程序和一个通过单击按钮启动的线程。让线程写入文件,然后休眠任意长的时间。当您确定它处于休眠状态时,请终止该应用程序。请注意,应用程序会立即终止,并且线程也会“在睡眠中被杀死”。
事实上,如果我们添加一个终结部分:
type
TTThread = class(TThread)
msg : string;
ctr : Integer;
public procedure Execute; override;
procedure Update;
end;
procedure TTThread.Execute;
var F: TextFile;
begin
ctr := 0;
assignFile(F, 'log.txt');
rewrite(f);
closefile(f);
while not Terminated do
begin
inc(ctr);
msg := 'Updating';
Synchronize(Update);
assignFile(F, 'log.txt');
append(f);
writeln(F, IntToStr(Ctr));
closefile(f);
msg := 'Sleeping';
Synchronize(Update);
Sleep(3000);
end;
end;
procedure TTThread.Update;
begin
Form1.Caption := '**********'+msg+IntToStr(ctr)+'******************';
end;
var T: TTThread;
procedure TForm1.Button1Click(Sender: TObject);
begin
if not assigned(T) then T := TTThread.Create(false);
end;
var F: TextFile;
initialization
finalization
assignFile(F, 'log.txt');
append(f);
writeln(F, 'Application out!');
closefile(f);
end.
(N.B。这是 而不是 呈现为线程安全代码,但它对实验很有用。)
您可以将调试器设置在终结中的最后一个 closeFile 并将其停放在那里,只要您愿意,线程就不会再次写入文件。这告诉我们,当最终代码命中时,拥有的线程已经死了。
根据您的兴趣程度,您还可以检查窗体的 OnClose、重写主窗体的 Close 方法等。
这在我们的理解上留下了一些漏洞,比如主窗体是否正式终止了每个线程,但我相信您可以从中弄清楚如何测试它。 (快速扫描表单源代码并没有特别揭示。)
我有一个线程通过事件循环执行工作和休眠一段时间(几秒钟)。用户可以在线程休眠等待事件时终止应用程序。在那种情况下,事件实际上发生了什么?线程是否保持 运行 直到事件超时,从而延迟应用程序的完全终止?还是 return 立即使用 return 值而不是超时?
虽然启动比创建它们的 Delphi 应用程序寿命更长的进程并非不可能,但以通常方式(通过 TThread.Create)创建和启动的线程会在主线程结束后立即结束,无需等待一个周期完成,也无需阻止主应用程序的终止。
要让自己相信这一点,请创建一个 Delphi 应用程序和一个通过单击按钮启动的线程。让线程写入文件,然后休眠任意长的时间。当您确定它处于休眠状态时,请终止该应用程序。请注意,应用程序会立即终止,并且线程也会“在睡眠中被杀死”。
事实上,如果我们添加一个终结部分:
type
TTThread = class(TThread)
msg : string;
ctr : Integer;
public procedure Execute; override;
procedure Update;
end;
procedure TTThread.Execute;
var F: TextFile;
begin
ctr := 0;
assignFile(F, 'log.txt');
rewrite(f);
closefile(f);
while not Terminated do
begin
inc(ctr);
msg := 'Updating';
Synchronize(Update);
assignFile(F, 'log.txt');
append(f);
writeln(F, IntToStr(Ctr));
closefile(f);
msg := 'Sleeping';
Synchronize(Update);
Sleep(3000);
end;
end;
procedure TTThread.Update;
begin
Form1.Caption := '**********'+msg+IntToStr(ctr)+'******************';
end;
var T: TTThread;
procedure TForm1.Button1Click(Sender: TObject);
begin
if not assigned(T) then T := TTThread.Create(false);
end;
var F: TextFile;
initialization
finalization
assignFile(F, 'log.txt');
append(f);
writeln(F, 'Application out!');
closefile(f);
end.
(N.B。这是 而不是 呈现为线程安全代码,但它对实验很有用。) 您可以将调试器设置在终结中的最后一个 closeFile 并将其停放在那里,只要您愿意,线程就不会再次写入文件。这告诉我们,当最终代码命中时,拥有的线程已经死了。
根据您的兴趣程度,您还可以检查窗体的 OnClose、重写主窗体的 Close 方法等。
这在我们的理解上留下了一些漏洞,比如主窗体是否正式终止了每个线程,但我相信您可以从中弄清楚如何测试它。 (快速扫描表单源代码并没有特别揭示。)