First part of solution is to make ForEach non-blocking. To do that, we just add a .NoWait modifier. We also have to store the interface returned from Parallel.ForEach call into some global field or ForEach object will be destroyed on the exit from the current method (i.e. the method in which Parallel.ForEach is called).
The problem now is how to destroy the FWorker interface. Parallel.ForEach provides an OnStop delegate which is called when the last worker thread finishes its job. The delegate is, however, called from the worker thread so we must not destroy FWorker in there. That would cause the ForEach object to be destroyed while the last worker is still running and would lead to a crash or a hanged program. A correct way is to schedule the cleanup to the main thread by using the Invoke method.
Destruction being taken care of, we still have to update the progress bar. To do that, worker calls IncrementProgressBar method via the Invoke mechanism (so that it is executed in the main thread and can update the VCL).
Because the values of i are not passed in order to the worker method, we cannot use them to determine the progress. Instead, the main form keeps its own count of work to be done. It is initialized before the Parallel.ForEach is created.
In the end, IncrementProgressBar, well, increments the progress bar. It also makes sure that we don’t overflow the Windows control with messages.
A surprisingly large number of hoops to jump through. Your lambda syntax looks cute. :) The Delphi language definitely is in dire need of some polish.
Regarding the use of mod, surely counting to 1000, then resetting would be more efficient than dividing by 1000 every time?
I don't know. Any way, the difference most probably wouldn't be measurable.
The mod is pobably a single CPU instruction. Integer math is really fast.
Yes, a division instruction which is one to two orders of magnitude slower than the other basic integer artihmetic instructions.
But you probably wouldn't notice in this case anyway.
I usually use "mod 1024" - i.e. mod on a multiple of 2.