作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
创建一个线程(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/
我是一名优秀的程序员,十分优秀!