Jump to content
uniGUI Discussion Forums
elGringo

OmniThreads and UniGUI

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?

Share this post


Link to post
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;

Share this post


Link to post
Share on other sites

I think the problem is that a webapp always works with request -> response. No active request, no response possible.

 

Due to the Async/Nowait you have: request -> response -> Callback function (but here is no request),

Share this post


Link to post
Share on other sites

thnks, but already in sunc mode

Use UniSession.Synchronize; then.

Share this post


Link to post
Share on other sites

Thanks, caisistemas!

Interesting solution with ajax. Also thought about it.

The more i work with UniGUI the more i understand - "first try ajax"))

 

rgreat

What you mean UniSession.Synchronize ?

Share this post


Link to post
Share on other sites
for i:=0 to 100 do begin
  pbForEach.Position := i;
  UniSession.Synchronize;
end;

UniSession.Synchronize is more or less analogue of VCL Application.ProcessMessages;

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×