我正在尝试在 Delphi 10.4 (Sydney) 中实现多线程。我使用 TTask 并发运行任务,使用 TThreadPool 限制同时运行的线程。
这是我的代码:
var
MyThreadPool: TThreadPool;
I: Integer;
Tasks: TArray<ITask>;
function ProcessTask(const TaskId: Integer): TProc;
begin
Result := procedure
Begin
WriteLn(Format('Started TaskId: %d ThreadId: %d',[TaskId,TThread.Current.ThreadID]));
Sleep(2000); // Simulate work
WriteLn(format('TaskId %d completed. ThreadId: %d',[TaskId, TThread.Current.ThreadID]));
End;
end;
begin
try
Writeln('Creating TThreadPool');
MyThreadPool := TThreadPool.Create;
try
MyThreadPool.SetMinWorkerThreads(1);
MyThreadPool.SetMaxWorkerThreads(4);
// Hold 10 tasks
SetLength(Tasks,10);
for I := 0 to High(Tasks) do
Begin
Tasks[I] := TTask.Create(
ProcessTask(I+1),
MyThreadPool
);
// Start the task
Tasks[I].Start;
End;
// Wait for all tasks to complete
for I := 0 to High(Tasks) do
Tasks[I].Wait;
WriteLn('All tasks completed.');
ReadLn;
finally
MyThreadPool.Free;
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
上述代码的输出是:
Creating TThreadPool
Started TaskId: 1 ThreadId: 17292
Started TaskId: 1 ThreadId: 17292
Started TaskId: 2 ThreadId: 19256
Started TaskId: 3 ThreadId: 25268
Started TaskId: 3 ThreadId: 25268
Started TaskId: 4 ThreadId: 21112
TaskId 1 completed. ThreadId: 17292
Started TaskId: 5 ThreadId: 17292
TaskId 2 completed. ThreadId: 19256
Started TaskId: 6 ThreadId: 19256
TaskId 3 completed. ThreadId: 25268
TaskId 3 completed. ThreadId: 25268
TaskId 4 completed. ThreadId: 21112
Started TaskId: 7 ThreadId: 21112Started TaskId: 8 ThreadId: 25268Started TaskId: 7 ThreadId: 21112Started TaskId: 8 ThreadId: 25268
TaskId 5 completed. ThreadId: 17292
Started TaskId: 9 ThreadId: 17292
TaskId 6 completed. ThreadId: 19256
Started TaskId: 10 ThreadId: 19256
TaskId 8 completed. ThreadId: 25268
TaskId 8 completed. ThreadId: 25268
TaskId 7 completed. ThreadId: 21112
TaskId 9 completed. ThreadId: 17292
TaskId 10 completed. ThreadId: 19256
All tasks completed.
代码的问题在于在某些情况下开始和完成报告会重复:
- Started TaskId出现了两次,分别为 TaskId 1,3,7,8。
- TaskId完成出现了两次,分别是 TaskId 3,8。
无需深入研究,问题很可能在于您使用的
WriteLn
是容易出现问题的多线程代码。在输出中添加某种同步,以确保WriteLn
一次只执行一个调用。