【发布时间】:2017-12-13 14:19:21
【问题描述】:
我正在等待线程完成,但是没有成功,它卡在了WaitFor()方法中;并且不回来,无限期地站在那里。
procedure TForm1.btnStopClick(Sender: TObject);
谁能帮帮我?
我正在使用 Delphi Berlin 10.1 Update 2,在 Windows 10 64 位版本 1709 16299.64 上运行
按照代码:
unit untPrincipal;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
const
WM_TEST_SERVICE = WM_APP + 1;
type
TForm1 = class(TForm)
btnStart: TButton;
mmoOutput: TMemo;
btnStop: TButton;
procedure btnStartClick(Sender: TObject);
procedure btnStopClick(Sender: TObject);
private
{ Private declarations }
threadService: TThread;
procedure OnThreadTerminate(Sender: TObject);
procedure WMTestService(var msg: TMessage); message WM_TEST_SERVICE;
public
{ Public declarations }
end;
IThreadInfo = interface
['{B179712B-8B14-4D54-86DA-AB22227DBCAA}']
function IsRunning: Boolean;
end;
IService = interface
['{30934A11-1FB9-46CB-8403-F66317B50199}']
procedure ServiceCreate();
procedure ServiceStart(const info: IThreadInfo);
end;
TMyService = class(TInterfacedObject, IService)
private
handle: THandle;
public
constructor Create(const handle: THandle);
procedure ServiceCreate;
procedure ServiceStart(const info: IThreadInfo);
end;
TThreadService = class(TThread)
private
service: IService;
protected
procedure Execute; override;
public
constructor Create(const service: IService);
end;
TThreadInfo = class(TInterfacedObject, IThreadInfo)
private
thread: TThread;
public
constructor Create(const thread: TThread);
function IsRunning: Boolean;
end;
TThreadPost = class(TThread)
private
handle: THandle;
info: IThreadInfo;
protected
procedure Execute; override;
public
constructor Create(const handle: THandle; const info: IThreadInfo);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TForm1 }
procedure TForm1.btnStartClick(Sender: TObject);
var
service: IService;
begin
service := TMyService.Create(Self.handle);
threadService := TThreadService.Create(service);
threadService.OnTerminate := OnThreadTerminate;
threadService.Start;
end;
procedure TForm1.btnStopClick(Sender: TObject);
begin
if Assigned(threadService) then
begin
try
threadService.Terminate;
threadService.WaitFor;
finally
if Assigned(threadService) then
FreeAndNil(threadService);
end;
end;
end;
procedure TForm1.OnThreadTerminate(Sender: TObject);
begin
mmoOutput.Lines.Add(DateTimeToStr(Now()) + ' - procedure TForm1.OnThreadTerminate(Sender: TObject);');
end;
procedure TForm1.WMTestService(var msg: TMessage);
begin
mmoOutput.Lines.Add(DateTimeToStr(Now()) + ' - Service');
end;
{ TMyService }
constructor TMyService.Create(const handle: THandle);
begin
inherited Create();
Self.handle := handle;
end;
procedure TMyService.ServiceCreate;
begin
PostMessage(handle, WM_TEST_SERVICE, 0, 0);
end;
procedure TMyService.ServiceStart(const info: IThreadInfo);
var
thread: TThreadPost;
begin
while info.IsRunning do
begin
thread := TThreadPost.Create(handle, info);
try
thread.Start;
thread.WaitFor;
ShowMessage('Never Execute');
finally
thread.Free;
end;
end;
end;
{ TThreadService }
constructor TThreadService.Create(const service: IService);
begin
inherited Create(True);
Self.service := service;
end;
procedure TThreadService.Execute;
begin
service.ServiceCreate;
service.ServiceStart(TThreadInfo.Create(Self) as IThreadInfo);
end;
{ TThreadInfo }
constructor TThreadInfo.Create(const thread: TThread);
begin
inherited Create();
Self.thread := thread;
end;
function TThreadInfo.IsRunning: Boolean;
begin
Result := not thread.CheckTerminated;
end;
{ TThreadPost }
constructor TThreadPost.Create(const handle: THandle; const info: IThreadInfo);
begin
inherited Create(True);
Self.handle := handle;
Self.info := info;
end;
procedure TThreadPost.Execute;
begin
while info.IsRunning do
begin
PostMessage(handle, WM_TEST_SERVICE, 0, 0);
Sleep(1000);
end;
end;
end.
【问题讨论】:
-
你为什么要在启动线程后调用它?为什么在那种情况下有一个线程?为什么线程从不检查
Terminated? -
这段代码只是为了显示我在一个更大的系统中遇到的一个问题,当我完成系统时,我在运行多个 IService 并且每个都有自己的线程(Windows 服务以防万一)我必须结束所有线程,等待相同的完成并执行其他操作,问题是我何时必须完成。每个 IService 的实现方式不同,在某些情况下,它内部运行的线程更多,这就是我发现问题的地方
-
@JerryDodge,你说WaitFor()方法是不必要的,但是此时我如何等待Thread结束呢?谢谢
-
主表单句柄可以随时重新创建。使用您自己的句柄来发布消息。见Is the TForm.Handle thread safe?。从线程调用
ShowMessage是错误的,因为vcl 不是线程安全的。 -
@LURD 感谢您的评论,但 ShowMessage 从未运行,因为代码在 WaitFor () 方法中停止。在 Handle 上,这只是 Threads 和 PostMessage 的问题,以至于当代码在 WaitFor() 方法中停止时,PostMessage 继续工作
标签: multithreading delphi delphi-10.1-berlin