Jump to content

OmniThreads and UniGUI


elGringo

Recommended Posts

Hi, trying example ProgressBar with forEach

but! doesn't work...

vcl example looks like this and works perfectly

unit test_55_ForEachProgress;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics,
  Controls, Forms, Dialogs, StdCtrls, ComCtrls,
 
  OtlTask,
  OtlParallel;
 
type
  TfrmForEachWithProgressBar = class(TForm)
    btnStart : TButton;
    pbForEach: TProgressBar;
    procedure btnStartClick(Sender: TObject);
  private
    FPosition: integer;
    FProgress: integer;
    FWorker  : IOmniParallelLoop<integer>;
    procedure IncrementProgressBar;
  end;
 
var
  frmForEachWithProgressBar: TfrmForEachWithProgressBar;
 
implementation
 
{$R *.dfm}
 
const
  CNumLoop = 20000;
 
procedure TfrmForEachWithProgressBar.btnStartClick(Sender: TObject);
begin
  btnStart.Enabled := false;
 
  pbForEach.Max := 100;
  pbForEach.Position := 0;
  pbForEach.Update;
  FProgress := 0;
  FPosition := 0;
 
  // reference must be kept in a global field so that the task controller is not destroyed before the processing ends
  FWorker := Parallel
    .ForEach(1, CNumLoop)
    .NoWait // important, otherwise message loop will be blocked while ForEach waits for all tasks to terminate
    .OnStop(
      procedure (const task: IOmniTask)
      begin
        // because of NoWait, OnStop delegate is invoked from the worker code; we must not destroy the worker at that point or the program will block
        task.Invoke(
          procedure begin
            FWorker := nil;
            btnStart.Enabled := true;
          end
        );
      end
    );
 
  FWorker.Execute(
    procedure (const task: IOmniTask; const i: integer)
    begin
      // do some work
      Sleep(1);
 
      // update the progress bar
      // we cannot use 'i' for progress as it does not increase sequentially
      // IncrementProgressBar uses internal counter to follow the progress
      task.Invoke(IncrementProgressBar);
    end
  );
end;
 
procedure TfrmForEachWithProgressBar.IncrementProgressBar;
var
  newPosition: integer;
begin
  Inc(FProgress);
  newPosition := Trunc((FProgress / CNumLoop)*pbForEach.Max);
  // make sure we don't overflow TProgressBar with messages
  if newPosition <> FPosition then begin
    pbForEach.Position := newPosition;
    FPosition := newPosition;
  end;
end;
 
end.

On UniGUI i tried...

  ProgressBar.Max := 100;
  ProgressBar.Position := 0;
  ProgressBar.Update;
  FProgress := 0;
  FPosition := 0;
    // reference must be kept in a global field so that the task controller is not destroyed before the processing ends
  FWorker := Parallel.ForEach(1, CNumLoop).NoWait // important, otherwise message loop will be blocked while ForEach waits for all tasks to terminate
    .OnStop(
    procedure(const task: IOmniTask)
    begin
        // because of NoWait, OnStop delegate is invoked from the worker code; we must not destroy the worker at that point or the program will block
      task.Invoke(
        procedure
        begin
          FWorker := nil;
          //btnStart.Enabled := true;
        end);
    end);

  FWorker.Execute(
    procedure(const task: IOmniTask; const i: integer)
    begin
      // do some work
      Sleep(1);

      // update the progress bar
      // we cannot use 'i' for progress as it does not increase sequentially
      // IncrementProgressBar uses internal counter to follow the progress
      task.Invoke(IncrementProgressBar);
    end);
procedure TForeCastSalesByDayCalcFrame.IncrementProgressBar;
var
  newPosition: integer;
begin
  Inc(FProgress);
  newPosition := Trunc((FProgress / CNumLoop) * ProgressBar.Max);
  // make sure we don't overflow TProgressBar with messages
  if newPosition <> FPosition then
  begin
    ProgressBar.Position := newPosition;
    FPosition := newPosition;
  end;
end;

What's wrong?

Link to comment
Share on other sites


begin
bForeCastForDevice.Enabled := false;
Parallel.Async(
procedure
begin
// executed in background thread
Caption := 'Work...';
Sleep(500);
// MessageBeep($FFFFFFFF);
end, Parallel.TaskConfig.OnTerminated(
procedure(const task: IOmniTaskControl)
begin
// executed in main thread
bForeCastForDevice.Enabled := true;
Caption := 'Ready';
end));
end;
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...