在我正在使用的應用程序中有幾個線程。 這些線程被設置爲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