multithreading - 使用 WaitForMultipleObjects 等待多个线程

标签 multithreading delphi delphi-xe

我正在使用 WaitForMultipleObjects 函数来等待多个线程的完成,但我做错了,因为结果不是预期的

查看示例代码

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
  end;

  TFoo = class(TThread)
  private
    Factor: Double;
    procedure ShowData;
  protected
    procedure Execute; override;
    constructor Create(AFactor : Double);
  end;


var
  Form1: TForm1;

implementation

Uses
 Math;

{$R *.dfm}

{ TFoo }

constructor TFoo.Create(AFactor: Double);
begin
  inherited Create(False);
  Factor := AFactor;
  FreeOnTerminate := True;

end;

procedure TFoo.Execute;
const
  Max=100000000;
var
  i : Integer;
begin
  inherited;
  for i:=1 to Max do
    Factor:=Sqrt(Factor);

  Synchronize(ShowData);
end;

procedure TFoo.ShowData;
begin
  Form1.Memo1.Lines.Add(FloatToStr(Factor));
end;

procedure TForm1.Button1Click(Sender: TObject);
const
 nThreads=5;
Var
 tArr  : Array[1..nThreads]  of TFoo;
 hArr  : Array[1..nThreads]  of THandle;
 i     : Integer;
 rWait : Cardinal;
begin
  for i:=1  to nThreads do
   begin
     tArr[i]:=TFoo.Create(Pi*i);
     hArr[i]:=tArr[i].Handle;
   end;

  repeat
    rWait:= WaitForMultipleObjects(nThreads, @hArr, True, 100);
    Application.ProcessMessages;
  until rWait<>WAIT_TIMEOUT;
  //here I want to show this message when all the threads are terminated    
  Memo1.Lines.Add('Wait done');
end;

end.

这是演示应用程序的当前输出

1
Wait done
1
1
1
1

但我想要这样的东西

1
1
1
1
1
Wait done

我必须如何使用 WaitForMultipleObjects 函数来等待所有线程终止?

最佳答案

修复:删除 FreeOnTerminate。

当您仍然需要句柄时,您的代码会导致线程被释放。这是一个很大的错误,您可能会在代码中的其他地方遇到访问冲突,或者从 WaitFormMultipleObjects 返回错误返回代码。

当 TThread 被释放时,TThread.handle 变得无效,并且这会提前终止等待循环,因为句柄不再有效。如果您在后台释放 TThread 后尝试访问它,您也可能会遇到访问访问冲突,因此我认为最好在已知时间有意释放它们。

使用线程句柄作为事件句柄工作正常,但您不应该在线程终止时使用 FreeOnTerminate 来释放线程,因为这会过早破坏句柄。

我也同意有人说用 Application.Processmessages 进行忙等待循环非常丑陋。还有其他方法可以做到这一点。

unit threadUnit2;

interface

uses Classes, SyncObjs,Windows, SysUtils;

type
  TFoo = class(TThread)
  private
    FFactor: Double;
    procedure ShowData;
  protected
    procedure Execute; override;
    constructor Create(AFactor : Double);
    destructor Destroy; override;
  end;

  procedure WaitForThreads;


implementation

Uses
 Forms,
 Math;

procedure Trace(msg:String);
begin
  if Assigned(Form1) then
    Form1.Memo1.Lines.Add(msg);
end;



{ TFoo }

constructor TFoo.Create(AFactor: Double);
begin
  inherited Create(False);
  FFactor := AFactor;
//  FreeOnTerminate := True;

end;

destructor TFoo.Destroy;
begin
  inherited;
end;

procedure TFoo.Execute;
const
  Max=100000000;
var
  i : Integer;
begin
  inherited;
  for i:=1 to Max do
    FFactor:=Sqrt(FFactor);


  Synchronize(ShowData);
end;


procedure TFoo.ShowData;
begin

  Trace(FloatToStr(FFactor));
end;

procedure WaitForThreads;
const
 nThreads=5;
Var
 tArr  : Array[1..nThreads]  of TFoo;
 hArr  : Array[1..nThreads]  of THandle;
 i     : Integer;
 rWait : Cardinal;
begin
  for i:=1  to nThreads do
   begin
     tArr[i]:=TFoo.Create(Pi*i);
     hArr[i]:=tArr[i].handle; // Event.Handle;
   end;

  repeat
    rWait:= WaitForMultipleObjects(nThreads, @hArr[1],{waitAll} True, 150);
    Application.ProcessMessages;
  until rWait<>WAIT_TIMEOUT;
  Sleep(0);
  //here I want to show this message when all the threads are terminated
  Trace('Wait done');

  for i:=1  to nThreads do
   begin
     tArr[i].Free;
   end;

end;

end.

关于multithreading - 使用 WaitForMultipleObjects 等待多个线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6867105/

相关文章:

delphi - Indy FTP 上传失败

delphi - TMemo 如何处理 Mac 上的回车(CRLF)问题?

delphi - 64 位 Windows 7、8 中 ShellExecuteW 的替代方案

java - 处理程序和接口(interface)可运行 - 有新线程

Delphi 字符串生成器

java - 线程局部

sql-server-2008 - 使用 Native Client 10 将 TDateTime 字段插入 SQL 2008 DB

forms - 查找嵌入在窗体中的窗体的屏幕位置,嵌入在窗体中,

java - 如何在java中为属性文件提供文件锁?

java - java中的跨类同步