The Dext Fluent Async API (Dext.Threading.Async) provides a modern, fluent interface for handling asynchronous operations in Delphi. It simplifies complex threading scenarios, pipeline chaining, error handling, and UI synchronization, making your code cleaner and more robust.
- Fluent Interface: Chain operations naturally using
ThenBy,OnComplete, andOnException. - Pipeline Execution: Pass results from one background task to the next automatically.
- Automatic UI Synchronization: Callbacks (
OnComplete,OnException) are automatically marshaled to the Main Thread, making UI updates safe and easy. - Cancellation Support: Integrated support for
ICancellationTokento cancel running pipelines gracefully. - Exception Handling: robust error handling that captures exceptions from background threads and delivers them to the main thread.
Add the unit to your usage clause:
uses
Dext.Threading.Async;Run a function in a background thread and handle the result on the main thread.
TAsyncTask.Run<Integer>(
function: Integer
begin
// This runs in a background thread
Sleep(1000);
Result := 42;
end)
.OnComplete(
procedure(Value: Integer)
begin
// This runs on the MAIN THREAD
ShowMessage('Result: ' + Value.ToString);
end)
.Start;You can chain multiple operations. The result of one step is passed as the input to the next.
TAsyncTask.Run<Integer>(
function: Integer
begin
// Step 1: Expensive calculation
Result := 10;
end)
.ThenBy<Integer>(
function(Input: Integer): Integer
begin
// Step 2: Transform the data
Result := Input * 2; // Returns 20
end)
.ThenBy<string>(
function(Input: Integer): string
begin
// Step 3: Format result
Result := 'Final Value: ' + Input.ToString;
end)
.OnComplete(
procedure(Result: string)
begin
// Final Output on UI
Label1.Caption := Result;
end)
.Start;If an exception occurs at any step in the pipeline, execution stops, and the OnException callback is triggered on the main thread.
TAsyncTask.Run<Integer>(
function: Integer
begin
raise Exception.Create('Database connection failed!');
end)
.ThenBy<string>(
function(Input: Integer): string
begin
// This will NOT run
Result := 'Success';
end)
.OnException(
procedure(E: Exception)
begin
// Handle error safely on Main Thread
ShowMessage('Error: ' + E.Message);
end)
.Start;You can cancel a running pipeline using a TCancellationTokenSource.
var
CTS: TCancellationTokenSource; // from Dext.Threading.CancellationToken
begin
CTS := TCancellationTokenSource.Create;
TAsyncTask.Run<Integer>(
function: Integer
begin
// Simulating long work
Sleep(5000);
Result := 100;
end)
.WithCancellation(CTS.Token) // Attach token
.OnComplete(
procedure(Val: Integer)
begin
ShowMessage('Completed');
end)
.OnException(
procedure(E: Exception)
begin
if E is EOperationCancelled then
ShowMessage('Task was cancelled!')
else
ShowMessage('Error: ' + E.Message);
end)
.Start;
// Call this elsewhere to cancel
CTS.Cancel;
end;You can also run tasks that don't return a value.
TAsyncTask.Run(
procedure
begin
// Do some background work
Log('Working...');
end)
.ThenBy(
procedure(Success: Boolean) // Receives Success boolean
begin
Log('Work done');
end)
.Start;For server-side applications where you don't need to update the UI, use default OnCompleteAsync and OnExceptionAsync.
These methods execute the callback on a background thread, avoiding the cost of synchronizing with the Main Thread.
TAsyncTask.Run<Integer>(
function: Integer
begin
Result := CalculateHeavyData();
end)
.OnCompleteAsync(
procedure(Result: Integer)
begin
// Runs on BACKGROUND thread
// Ideal for logging, writing to DB, or triggering other background tasks
Log('Calculation finished: ' + Result.ToString);
end)
.OnExceptionAsync(
procedure(E: Exception)
begin
// Runs on BACKGROUND thread
Log('Error: ' + E.Message);
end)
.Start;- Start(): You must call
.Startat the end of the chain to begin execution. - Thread Safety: Code inside
.Run,.ThenBy,.OnCompleteAsyncand.OnExceptionAsyncruns in a Background Thread. Do not access UI components directly from these methods. - UI Updates: Code inside
.OnCompleteand.OnExceptionruns in the Main Thread. This is the only safe place to update the UI. - TAsyncTask: Returns an
IAsyncTaskinterface (which inherits fromITask). You can hold a reference to it if needed.
Built with ❤️ for the Dext Framework.