Reputation: 2552
I know TTask
and have used TTask.WaitForAll(array)
successfully, as well as TParallel.&For()
.
But now I want to do a seemingly simple thing and don't find out how:
I have an unknown number of items coming in, this can be millions or only a few, and I don't know in advance. How can I work on them in parallel (just about 4 threads or so), but without a queue? If max threads are already busy, I want to wait for the next free slot. Something like a TTask.Run()
which just doesn't come back until it really starts running.
I guess I'm just overseeing something simple...?
When I'm through, I want to wait for all remaining tasks to finish. But of course I don't want to have millions of them in an array for WaitForAll()
.
I can imagine a possible solution (but I don't like it and hope for a much easier one using TTask
or similar):
TThreadedQueue
, it would automatically let me wait if the queue is fullI know this might be the preferred way anyway in some cases, but my situation would not profit from it (like reusing any objects, connections or so).
Pseudocode of what would be nice and clean:
MyThreadPool:= TMyThreadPool.Create(4);
while GetNextItem(out Item) do
//the following comes back when it has really been started:
MyThreadPool.Run(procedure begin Work(Item); end);
MyThreadPool.WaitFor;
Upvotes: 2
Views: 1161
Reputation: 2552
This seems to be a working solution, but abusing TParallel.&For
is maybe not really nice. I'm still hoping for a better answer.
if FindFirst(Path, 0, SearchRec) = 0 then
try
TParallel.&For(0, 99999,
procedure(I: Integer; LoopState: TParallel.TLoopState)
var
Filename: string;
begin
if LoopState.ShouldExit then Exit;
TMonitor.Enter(Self);
try
Filename:= SearchRec.Name;
if (FindNext(SearchRec) <> 0) or TThread.CheckTerminated then
LoopState.Stop; //or .Break?
finally
TMonitor.Exit(Self);
end;
try
ProcessFile(Filename);
except
on E: Exception do Log(E.ToString); //maybe also want to Stop
end;
end);
finally
FindClose(SearchRec);
end;
I wrote a lot of trace logs and it looks good. The only bad thing is that after the last file it still starts 10-20 more executions which are then exited at the beginning.
It also seems the default threadpool cannot be restricted to less than the number of processors.
Please comment if you think anything is bad or can/should be improved.
Upvotes: 2