简体   繁体   中英

How to show progress in the parallel threads

I have a code like this:

procedure TSeries.Read;
var
 ReadProc: TParallelFunction2;
 Counter:  integer;
begin
 try
  ProgressForm.Show;
  Counter  := 0;
  ReadProc :=
   procedure (i1, i2, tdi: integer)
   var
    i: integer;
   begin
    for i := i1 to i2 do
     if not FDASlice[i].PctPresent then
     begin
      TInterlocked.Increment(Counter);
      ReadSlice(i, True);
     end;
   end;

  Parallel.ForI(0, High, ReadProc, pfDivide);
 finally
  ProgressForm.HideForm;
 end;
end;

It uses the STParallel library to process the ReadProc procedure in the multi-threading mode. All works fine, but I need to show the progress to the user. I try to add the 'Application.ProcessMessage' + 'ProgressForm.SpTBXProgressBar1.Position := Counter' into the ReadProc, or the 'TThread.Synchronize' with no success. Application hangs, progress doesn't shows.

How I can do show the progress? Is it possible in that code at all, or it's needed to move all not-main threads to other place? Thank you.

The simplest, and best, way to deal with this is to have the main thread update the progress on a timer.

You need to give the timer event access to the progress counter. That means converting the Counter variable from a local variable, to be a variable of a class that the UI can access. You don't need to synchronize access to the counter because the UI is not modifying it, and you already use an atomic increment function to modify the counter.

So, the steps you need are:

  1. Move the Counter variable to be a member of a class, one that the UI can access.
  2. Add a timer to the UI with an appropriate update frequency. An timer interval of 100ms will be more than adequate.
  3. In the timer event set the progress bar's position to the instantaneous value of the counter.

So why is this approach better than yours? Well, progress UI updates should not be driven by the worker threads. Doing so runs the risk of overwhelming the UI with refreshes. This can put a serious block on perfmance and scalability.

Instead have the workers update progress state, but let the UI remain in charge of driving the updates. The UI knows that there's no point refreshing too frequently, and only it is in a position to determine refresh rate.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM