Jump to content


Photo

OmniThreads and UniGUI


  • Please log in to reply
11 replies to this topic

#1 elGringo

elGringo

    Advanced Member

  • uniGUI Subscriber
  • PipPipPipPip
  • 394 posts

Posted 09 February 2018 - 08:15 AM

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?


  • 0

#2 elGringo

elGringo

    Advanced Member

  • uniGUI Subscriber
  • PipPipPipPip
  • 394 posts

Posted 09 February 2018 - 08:20 AM

Async example seems doesn't work too


  • 0

#3 elGringo

elGringo

    Advanced Member

  • uniGUI Subscriber
  • PipPipPipPip
  • 394 posts

Posted 09 February 2018 - 08:20 AM

  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;

  • 0

#4 Oliver Morsch

Oliver Morsch

    Advanced Member

  • uniGUI Subscriber
  • PipPipPipPip
  • 214 posts
  • LocationGermany

Posted 09 February 2018 - 09:25 AM

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),


  • 0

#5 elGringo

elGringo

    Advanced Member

  • uniGUI Subscriber
  • PipPipPipPip
  • 394 posts

Posted 09 February 2018 - 09:42 AM

sucks(

as usual will use httpServer on Indy...


  • 0

#6 rgreat

rgreat

    Advanced Member

  • uniGUI Subscriber
  • PipPipPipPip
  • 161 posts

Posted 09 February 2018 - 11:02 AM

You could use synchronous unigui mode.


  • 0

#7 elGringo

elGringo

    Advanced Member

  • uniGUI Subscriber
  • PipPipPipPip
  • 394 posts

Posted 09 February 2018 - 11:03 AM

thnks, but already in sunc mode


  • 0

#8 caisistemas

caisistemas

    Active Member

  • uniGUI Subscriber
  • PipPipPip
  • 74 posts

Posted 09 February 2018 - 11:43 AM

To implement a ProgressBar try the attached code.

Attached Files

  • Attached File  Main.zip   7.19KB   11 downloads

  • 0

#9 rgreat

rgreat

    Advanced Member

  • uniGUI Subscriber
  • PipPipPipPip
  • 161 posts

Posted 09 February 2018 - 04:25 PM

thnks, but already in sunc mode

Use UniSession.Synchronize; then.


  • 0

#10 elGringo

elGringo

    Advanced Member

  • uniGUI Subscriber
  • PipPipPipPip
  • 394 posts

Posted 09 February 2018 - 10:04 PM

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 ?


  • 0

#11 rgreat

rgreat

    Advanced Member

  • uniGUI Subscriber
  • PipPipPipPip
  • 161 posts

Posted 11 February 2018 - 02:34 AM

for i:=0 to 100 do begin
  pbForEach.Position := i;
  UniSession.Synchronize;
end;

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


  • 0

#12 elGringo

elGringo

    Advanced Member

  • uniGUI Subscriber
  • PipPipPipPip
  • 394 posts

Posted 11 February 2018 - 08:27 AM

hm... need to try thnks!


  • 0




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users