Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Catalog · How the catalog works

Random project

VSoft.Awaitable

Async/Await for Delphi

View on GitHub

Anyone may press Interesting, signed in or not. It helps others find this project.

Member rating

No ratings yet.

Sign in to rate this project.

README

VSoft.Awaitable

This is a simple library for making Asynchronous function calls. It is built on standard Delphi threading primitives (TThread) and has no third‑party dependencies other than VSoft.CancellationToken.

It provides a simple way to run work on a background thread, cancel it and be notified of the cancellation, return typed results, and have your completion/exception/cancellation callbacks invoked back on the calling thread.

Usage

Include VSoft.Awaitable in your uses clause.

delphi
    TAsync.Configure<string>(
        function (const cancelToken : ICancellationToken) : string
        var
          i: Integer;
        begin
            result := 'Hello ' + value;
            for i := 0 to 2000 do
            begin
              Sleep(1);
              //in loops, check the token
              if cancelToken.IsCancelled then
                exit;
            end;

            //where api's can take a handle for cancellation, use the token.handle
            WaitForSingleObject(cancelToken.Handle,5000);

            //any unhandled exceptions here will result in the on exception proc being called (if configured)
            //raise Exception.Create('Error Message');
        end, token);
    )
    .OnException(
        procedure (const e : Exception)
        begin
          Label1.Caption := e.Message;
        end)
    .OnCancellation(
        procedure
        begin
            //clean up
            Label1.Caption := 'Cancelled';
        end)
    .Await(
        procedure (const value : string)
        begin
            //use result
            Label1.Caption := value;
        end);

You can also return IAwaitable<TResult> from functions

delphi
function LoadAsyncWithToken (const token : ICancellationToken; const value : string) : IAwaitable<string>;
begin
  //configure our async call and return the IAwaitable<string>
  result := TAsync.Configure<string>(
        function(const cancelToken : ICancellationToken) : string
        begin
            //.... do some long running thing
            result := 'Hello ' + value;
        end, token);
end;

// for when there is no result to return
function RunIt (const token : ICancellationToken; const value : string) : IAwaitable;
begin
  //configure our async call and return the IAwaitable<string>
  result := TAsync.Configure(
        procedure(const cancelToken : ICancellationToken)
        begin
        //.... do some long running thing
        end, token);
end;

procedure UseIt;
begin
     LoadAsyncWithToken('param', FTokenSource.Token)
     .OnException(
        procedure (const e : Exception)
        begin
          Label1.Caption := e.Message;
        end)
    .OnCancellation(
        procedure
        begin
            //clean up
            Label1.Caption := 'Cancelled';
        end)
    .Await(
        procedure (const value : string)
        begin
            //use result
            Label1.Caption := value;
        end);

     RunIt('param', FTokenSource.Token)
     .OnException(
        procedure (const e : Exception)
        begin
          Label1.Caption := e.Message;
        end)
    .OnCancellation(
        procedure
        begin
            //clean up
            Label1.Caption := 'Cancelled';
        end)
    .Await(
        procedure
        begin
            //use result
            Label1.Caption := 'Done';
        end);

Note that Await actually invokes the async function. There is also an overload to TAsync.Configure that does not take a cancellation token for when you don't need to cancel.