在我正在使用的应用程序中有几个线程。 这些线程被设置为FreeOnTerminate,我不允许改变这种行为。 我看到一些奇怪的老开发人员正在等待在主线程中的一些信号的方式,如下:如何等待多个事件?
令:
var FWaits: array of TEvent;
var FThreads: array of TBkgThread;
const C = 10;
为每个线程,我们有一个事件,然后Length(Threads) = Length(FWaits)
for I:= 0 to C-1 do
begin
FWaits[I]:= TSimpleEvent.Create;
FThreads[I]:= TBkgThread.Create(FWaits[I]); //The handle of the Event
end;
[CODE]
for I:= 0 to Length(FWaits)-1 do
case FWaits[I].WaitFor(INFINITE) of
wrError: begin
NotifyError; //Code Irrevelant;
Break;
end;
wrSignaled: TryNotifyUser(I); //Code Irrevelant;
wrAbandoned: TryNotifyAbandon(I); //Code Irrevelant;
wrTimeout: TryNotifyTimeOut(I); //Code Irrevelant;
end;
这样安排是在工作线程:
destructor TBkgThread.Destroy;
begin
inherited;
FEvent.SetEvent;
end;
我不知道在这种情况下调用继承的信号是否正常,但这不是问题的一部分。
我知道WaitForMultipleObjects的,所以我试图减少打上[CODE]
这个代码:
var Handles: array of THandle;
SetLength(Handles, Length(FWaits));
for I:= 0 to Length(FWaits)-1 do
Handles[I]:= FWaits[I].Handle;
case WaitForMultipleObjects(Length(Handles), @Handles[0], TRUE, INFINITE) of
WAIT_FAILED: begin Label1.Caption:= 'WAIT_FAILED'; RaiseLastWin32Error; end;
WAIT_OBJECT_0: Label1.Caption:= 'WAIT_OBJECT_0';
WAIT_ABANDONED_0: Label1.Caption:= 'WAIT_ABANDONED_0';
WAIT_TIMEOUT: Label1.Caption:= 'WAIT_TIMEOUT';
end;
但它提高了Windows错误:代码6.
我怎样才能正确地等待多个事件?
[更新]
TBkgThread = class(TThread)
private
FEvent: TEvent;
protected
procedure Execute; override;
public
constructor Create(AEvent: TEvent);
destructor Destroy; override;
end;
TForm1 = class(TForm)
edThreads: TLabeledEdit;
Button1: TButton;
Button2: TButton;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
FThreads: array of TBkgThread;
FWaits: array of TEvent;
public
{ Public declarations }
end;
{ TBkgThread }
constructor TBkgThread.Create(AEvent: TEvent);
begin
inherited Create(False);
FreeOnTerminate:= True;
FEvent:= AEvent;
end;
destructor TBkgThread.Destroy;
begin
inherited;
FEvent.SetEvent;
end;
procedure TBkgThread.Execute;
var I,J,K: Integer;
begin
while not Terminated do
begin
for I:= 0 to 10000 div 20 do
for J:= 0 to 10000 div 20 do
for K:= 0 to 10000 div 20 do;
Sleep(1000);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
I, C: Integer;
begin
C:= StrToIntDef(edThreads.Text, 0);
if C > 0 then
begin
SetLength(FThreads, C);
SetLength(FWaits, C);
for I:= 0 to C-1 do
begin
FWaits[I]:= TSimpleEvent.Create();
FThreads[I]:= TBkgThread.Create(FWaits[I]);
end;
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
var I: Integer;
Handles: array of THandle;
begin
for I:= 0 to Length(FWaits)-1 do
FThreads[I].Terminate;
SetLength(Handles, Length(FWaits));
for I:= 0 to Length(FWaits)-1 do
Handles[I]:= FWaits[I].Handle;
case WaitForMultipleObjects(Length(Handles), @Handles[0], TRUE, INFINITE) of
WAIT_FAILED: begin RaiseLastWin32Error; Label1.Caption:= 'WAIT_FAILED'; end;
WAIT_OBJECT_0: Label1.Caption:= 'WAIT_OBJECT_0';
WAIT_ABANDONED_0: Label1.Caption:= 'WAIT_ABANDONED_0';
WAIT_TIMEOUT: Label1.Caption:= 'WAIT_TIMEOUT';
end;
// for I:= 0 to Length(FWaits)-1 do
// case FWaits[I].WaitFor(INFINITE) of
// wrError: begin Label1.Caption:= 'WAIT_FAILED'; Break; end;
// wrSignaled: Label1.Caption:= 'WAIT_OBJECT_0';
// wrAbandoned: Label1.Caption:= 'WAIT_ABANDONED_0';
// wrTimeout: Label1.Caption:= 'WAIT_TIMEOUT';
// end;
end;
我不知道SSCCE是否有必要。如果需要,我可以发布。 – EProgrammerNotFound 2014-10-06 12:49:27
你不能等待终止线程上的空闲。启动后,您不能保留对它们的引用。您需要重新考虑设计无法更改的限制。这使得解决问题非常棘手。 – 2014-10-06 12:53:18
我正在等待事件,而不是线程 – EProgrammerNotFound 2014-10-06 12:53:41