3
votes

I have several task on button click.

eg.

  1. Show form or please wait panel....
  2. Load data from database (duration 5-10 seconds)
  3. Clear all TEdit field
  4. Hide form or please wait panel....
  5. ShowMessage('completed')

Is it possible After click on button show please wait panel or form and after all completed hide that panel.

How to Synchronize Perform Tasks One by one.

Or any other simple solution.

1

1 Answers

5
votes

This is a simple example that creates a "placeholder" which looks like this:

enter image description here

The rectangle has a black background and contains a layout which is aligned to Center; inside you can find a label (aligned to Top) and an arc (aligned to Client). The code is here:

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 418
  ClientWidth = 490
  FormFactor.Width = 320
  FormFactor.Height = 480
  FormFactor.Devices = [Desktop]
  OnCreate = FormCreate
  DesignerMasterStyle = 0
  object Rectangle1: TRectangle
    Align = Client
    Fill.Color = xFF222222
    Size.Width = 490.000000000000000000
    Size.Height = 418.000000000000000000
    Size.PlatformDefault = False
    Visible = False
    object Layout1: TLayout
      Align = Center
      Size.Width = 170.000000000000000000
      Size.Height = 102.000000000000000000
      Size.PlatformDefault = False
      TabOrder = 0
      object Label1: TLabel
        Align = Top
        StyledSettings = [Family, Size, Style]
        Size.Width = 170.000000000000000000
        Size.Height = 41.000000000000000000
        Size.PlatformDefault = False
        TextSettings.FontColor = claWhite
        TextSettings.HorzAlign = Center
        Text = 'Please wait'
        TabOrder = 0
      end
      object Arc1: TArc
        Align = Center
        Size.Width = 50.000000000000000000
        Size.Height = 50.000000000000000000
        Size.PlatformDefault = False
        Stroke.Color = claCoral
        EndAngle = -90.000000000000000000
        object FloatAnimation1: TFloatAnimation
          Enabled = True
          Duration = 1.000000000000000000
          Loop = True
          PropertyName = 'RotationAngle'
          StartValue = 0.000000000000000000
          StopValue = 360.000000000000000000
        end
      end
    end
  end
end

The Visible property of the rectangle is set to False so that you won't see immediately the rectangle. Note that I have created an animation in the arc component so that you can see it spinning around:

enter image description here

In this way you can mimic a loading spinner. Then I have added this code in the OnCreate event of the form just as example of how you could do this.

procedure TForm1.FormCreate(Sender: TObject);
begin
  TTask.Run(procedure
            begin
              TThread.Synchronize(nil, procedure
                                 begin
                                   Rectangle1.Visible := true;
                                   //Rectangle1.BringToFront;
                                   // ^ call the above if needed, just to be sure
                                   // that you'll always see the rectangle on screen 
                                 end);

              Sleep(4000);

              TThread.Synchronize(nil, procedure
                                 begin
                                   Rectangle1.Visible := false;
                                   ShowMessage('Finish!');
                                 end);
            end);
end;

The Sleep(4000) simulates a long task and this piece of code should be replaced with your tasks. Actually I'd do something like this:

procedure TForm1.FormCreate(Sender: TObject);
begin
  TTask.Run(procedure
            var
              arr: array [0..1] of ITask;
            begin
              TThread.Synchronize(nil, procedure
                                 begin
                                   Rectangle1.Visible := true;
                                   Rectangle1.BringToFront;
                                 end);

              arr[0] := TTask.Run(procedure
                                  begin
                                    //load data from the database
                                  end);

              arr[1] := TTask.Run(procedure
                                  begin
                                    //something else
                                  end);

              //this call is blocking but you are calling this in a worker thread!
              //your UI won't freeze and at the end you'll see the message appearing
              TTask.WaitForAll(arr);
              TThread.Synchronize(nil, procedure
                                 begin
                                   Rectangle1.Visible := false;
                                   ShowMessage('Finish!');
                                 end);
            end);
end;

Of course you should place this code in a ButtonClick and not in a FormCreate event handler!