Table of Contents

Class Awaiter

Namespace
Cuemon.Threading
Assembly
Cuemon.Kernel.dll

Provides a set of static methods for awaiting asynchronous operations.

public static class Awaiter
Inheritance
Awaiter

Examples

The following example retries an asynchronous operation until it succeeds or the retry window closes. The delegate returns UnsuccessfulValue twice before returning SuccessfulValue, and the configured cancellation token is observed between attempts.

using System;
using System.Threading;
using System.Threading.Tasks;
using Cuemon.Threading;

namespace Cuemon.Threading;

public class AwaiterExample
{
    public async Task DemonstrateAsync()
    {
        var attempt = 0;
        var cancellationSource = new CancellationTokenSource(TimeSpan.FromSeconds(10));

        var result = await Awaiter.RunUntilSuccessfulOrTimeoutAsync(async () =>
        {
            attempt++;
            if (attempt < 3)
            {
                await Task.Delay(50);
                return new UnsuccessfulValue();
            }
            return new SuccessfulValue();
        }, options =>
        {
            options.Timeout = TimeSpan.FromSeconds(5);
            options.Delay = TimeSpan.FromMilliseconds(100);
            options.CancellationToken = cancellationSource.Token;
        });

        Console.WriteLine($"Succeeded after {attempt} attempts: {result.Succeeded}");
    }
}

Methods

RunUntilSuccessfulOrTimeoutAsync(Func<Task<ConditionalValue>>, Action<AsyncRunOptions>)

Repeatedly invokes the specified asynchronous method until it succeeds, cancellation is requested, the configured attempt limit is reached, or the configured Timeout retry window closes.

public static Task<ConditionalValue> RunUntilSuccessfulOrTimeoutAsync(Func<Task<ConditionalValue>> method, Action<AsyncRunOptions> setup = null)

Parameters

method Func<Task<ConditionalValue>>

The asynchronous function delegate to execute, returning a ConditionalValue indicating success or failure.

setup Action<AsyncRunOptions>

The AsyncRunOptions which may be configured.

Returns

Task<ConditionalValue>

A task that represents the asynchronous operation. The task result contains the successful ConditionalValue returned by method, or an unsuccessful value that aggregates caught exceptions when the retry policy completes without success.

Remarks

The retry window begins immediately before the initial invocation. The initial invocation always occurs, even when Timeout is Zero. No new invocation begins after the timeout deadline or once MaximumAttempts is reached. After an unsuccessful attempt or a caught exception, the next delay is capped to the smaller of Delay and the remaining timeout window. When the configured delay exceeds the remaining timeout window, the operation waits out the remainder of the window and completes without starting another invocation. Positive fractional-millisecond retry delays are rounded up to the next whole millisecond when the delay is scheduled. When Delay is Zero, MaximumAttempts must be configured with a positive value.

Cancellation is resolved from CancellationToken immediately before each attempt and immediately before each retry delay. Because this overload does not pass a CancellationToken into method, timeout and cancellation cannot terminate work that is already executing inside the delegate; they only prevent additional retries or delays once the current invocation completes.

A completed invocation returning null is treated as a programming error and causes an InvalidOperationException without retrying. Potential exceptions thrown by method are caught and collected. If the operation does not succeed before the retry policy completes, UnsuccessfulValue will be conditionally initialized as follows: 1: No caught exceptions; initialized with the default constructor. 2: One caught exception; initialized with the caught exception. 3: Two or more caught exceptions; initialized with an AggregateException containing the caught exceptions in encounter order.

Timeout does not abort an invocation already in progress. The current invocation is allowed to complete, and a successful result is returned even when it arrives after the timeout deadline. If an in-flight invocation completes unsuccessfully or throws after the deadline, the retry policy ends without another delay or attempt.

Exceptions

ArgumentNullException

method cannot be null.

ArgumentException

The configured AsyncRunOptions are not in a valid state.

InvalidOperationException

method completed successfully but returned a null ConditionalValue.

OperationCanceledException

Cancellation was requested before an attempt began, while a retry delay was pending, or method threw an OperationCanceledException.