Skip to content
Dmitry Streblechenko edited this page Dec 15, 2019 · 2 revisions

To use this library, add AsyncAwait to the uses clause; you can then create code like the following:

procedure TForm1.btnFibonacciClick(Sender: TObject);
var
  seed: UInt64;
begin
  seed := Random(MaxInt);
  lblResult.Caption := Format('Calculating Fibonacci number for %d. Please wait...', [seed]);
  TTask<UInt64>.Async(
              //timeconsuming call on a secondary thread
              function : UInt64
              begin
                Result := Fibonacci(seed);
              end,
              //update the UI on the main thread
              procedure(task : ITask<UInt64>; Value : UInt64)
              begin
                if task.Status = TTaskStatus.RanToCompletion
                  then lblResult.Caption := Format('Fibonacci number for %d is %d', [seed, Value])
                else if task.Status = TTaskStatus.Faulted
                  then lblResult.Caption := Format('Error calculating Fibonacci number: %s', [task.Exception.Message])
              end,
              //tell to continue on the main thread -
              //don't need to specify this parameter as it defaults to true anyway
              true
              );
end;

You can also specify a particular synchronization context even if you start a new task on a secondary thread:

procedure TForm1.Button1Click(Sender: TObject);
var
  t : ITask<integer>;
  syncContext : ISynchronizationContext;
begin
  syncContext := TSynchronizationContext.Current;

  t := TTask<integer>.Async(

              //async function
              function() : integer
              var
                delay : integer;
              begin
                delay := Random(10000);
                sleep(delay);
                Result := delay;
                //run another task
                //start it explicitly since we need to configure the
                //synchornization context (main thread) first
                //before the continuation code has a chance to run
                TTask.Create(
                     procedure()
                     begin
                       sleep(2000);
                     end
                   ).
                   ContinueWith(
                     procedure(task : ITask)
                     begin
                       ShowMessage('Done second task');
                     end,
                     //use the sync context from the main thread since we are showing a window
                     syncContext
                     ).
                   //now start the task after we configured it
                   Start;
              end,

              //continue with
              //it is guaranteed to run on the calling thread (this main thread)
              //since continueOnCapturedContext parameter defaults to true
              procedure(task : ITask<integer>; Value : integer )
              begin
                if task.Status = TTaskStatus.RanToCompletion
                  then ShowMessage(Format('All done after sleeping for %d seconds', [task.Value div 1000]))
                else if task.Status = TTaskStatus.Faulted
                  then ShowMessage(Format('Task faulted. Exception type = %s: %s', [task.Exception.ClassName, task.Exception.Message]))
              end,
              //continue on the main thread - don't need to specify this parameter as it defaults to true
              true
                );
  if t.Wait(2000)
    then ShowMessage(Format('Done after waiting for less than 2 seconds. Task returned %d', [t.Value]))
    else ShowMessage('Still not done after waiting for 2 seconds');
end;
Clone this wiki locally