gpt4 book ai didi

multithreading - 多个连续线程上的 TThread.WaitFor

转载 作者:行者123 更新时间:2023-12-03 04:55:47 28 4
gpt4 key购买 nike

创建一个线程(TThreadStarter),然后它将创建许多工作线程,并且必须等待它们完成才能继续。它必须在 Linux 和 Windows 下都能工作。

下面的方法似乎是一个解决方案。但这是一件好事吗?你会采取不同的做法吗?

1) 创建所有线程并将其放入一个数组中,然后运行该数组并调用 Start。

2) 然后只需再次运行数组并调用 WaitFor 即可停止执行对于调用线程,直到所有线程都完成。

procedure TThreadStarter.Execute;
var i1:integer;
begin
for i1:=1 to WORK_THREAD_COUNT do ThreadArray[i1].Start;
for i1:=1 to WORK_THREAD_COUNT do ThreadArray[i1].WaitFor;

..Do some work

end;

我使用 Lazarus 和 FreePascal。

最佳答案

等待(几乎)任意数量的工作线程的解决方案(仅限 Windows)。

从您的 MainWorkerThread(不是普通的主线程)调用 WaitForThreads 函数,并传入您想要等待的所有线程句柄的数组。

interface

uses
Windows, SysUtils, Classes;

type
THandleDynArray = array of THandle;

TMaximum_Wait_Objects_Handles = array[0..MAXIMUM_WAIT_OBJECTS - 1] of THandle;

EMaximum_Handles_Exceeded = class(Exception);

TThreadWaitForThreads = class(TThread)
strict private
FarrHandle: TMaximum_Wait_Objects_Handles;
FThreadWaitCount: 0..MAXIMUM_WAIT_OBJECTS;
protected
procedure Execute; override;
public
procedure AddHandle(Handle: THandle); overload;
procedure AddHandle(HandleArray: THandleDynArray); overload;
procedure ClearHandles;
end;

procedure WaitForThreads(const Handles: THandleDynArray);

implementation

procedure WaitForThreads(const Handles: THandleDynArray);
var
Wait_Result: cardinal;
arrHandle: TMaximum_Wait_Objects_Handles;
arrWaitThreads: array[0..MAXIMUM_WAIT_OBJECTS - 1] of TThreadWaitForThreads;
WaitThreadsCount, i: integer;
begin
if Length(Handles) <= 0 then
exit;

if Length(Handles) > MAXIMUM_WAIT_OBJECTS then
begin
WaitThreadsCount := Length(Handles) div MAXIMUM_WAIT_OBJECTS;

for i := 0 to WaitThreadsCount - 1 do
begin
arrWaitThreads[i] := TThreadWaitForThreads.Create(true);
arrHandle[i] := arrWaitThreads[i].Handle;

arrWaitThreads[i].AddHandle(Copy(Handles, MAXIMUM_WAIT_OBJECTS * i, MAXIMUM_WAIT_OBJECTS));
end;

try
if Length(Handles) mod MAXIMUM_WAIT_OBJECTS > 0 then
Move(Handles[MAXIMUM_WAIT_OBJECTS * WaitThreadsCount], arrHandle[WaitThreadsCount], (Length(Handles) - WaitThreadsCount * MAXIMUM_WAIT_OBJECTS) * SizeOf(THandle));

for i := 0 to WaitThreadsCount - 1 do
arrWaitThreads[i].Resume;

repeat
Wait_Result := WaitForMultipleObjectsEx(WaitThreadsCount + Length(Handles) - WaitThreadsCount * MAXIMUM_WAIT_OBJECTS, @arrHandle, true, 10, true);
Application.ProcessMessages;
until ((Wait_Result <> WAIT_TIMEOUT)
and (Wait_Result <> WAIT_IO_COMPLETION));

finally
for i := 0 to WaitThreadsCount - 1 do
begin
arrWaitThreads[i].Terminate; // terminating all WaitThreads to be on the safe side
arrWaitThreads[i].Free;
end;
end;
end
else
begin
repeat
Wait_Result := WaitForMultipleObjectsEx(Length(Handles), @Handles[0], true, 10, true);
Application.ProcessMessages;
until ((Wait_Result <> WAIT_TIMEOUT)
and (Wait_Result <> WAIT_IO_COMPLETION));
end;
end;

{ TThreadWaitForThreads }

procedure TThreadWaitForThreads.AddHandle(Handle: THandle);
begin
if FThreadWaitCount < MAXIMUM_WAIT_OBJECTS then
begin
FarrHandle[FThreadWaitCount] := Handle;
Inc(FThreadWaitCount);
end
else
raise EMaximum_Handles_Exceeded.Create('You can only wait for ' + IntToStr(MAXIMUM_WAIT_OBJECTS) + ' Threads!');
end;

procedure TThreadWaitForThreads.AddHandle(HandleArray: THandleDynArray);
begin
if FThreadWaitCount + Length(HandleArray) <= MAXIMUM_WAIT_OBJECTS then
begin
Move(HandleArray[0], FarrHandle[FThreadWaitCount], SizeOf(THandle) * Length(HandleArray));
Inc(FThreadWaitCount, Length(HandleArray));
end
else
raise EMaximum_Handles_Exceeded.Create('You want to wait for ' + IntToStr(FThreadWaitCount + Length(HandleArray)) + ' threads, but you can only wait for ' + IntToStr(MAXIMUM_WAIT_OBJECTS) + '!');
end;

procedure TThreadWaitForThreads.ClearHandles;
begin
FThreadWaitCount := 0;
ZeroMemory(@FarrHandle, SizeOf(FarrHandle));
end;

procedure TThreadWaitForThreads.Execute;
var
Wait_Result: cardinal;
begin
if FThreadWaitCount = 0 then
exit;

repeat
Wait_Result := WaitForMultipleObjectsEx(FThreadWaitCount, @FarrHandle, true, 10, true);
until ((Wait_Result <> WAIT_TIMEOUT)
and (Wait_Result <> WAIT_IO_COMPLETION))
or Terminated;

ClearHandles;
end;

end.

关于multithreading - 多个连续线程上的 TThread.WaitFor,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27865019/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com