Tuesday, November 18, 2014

Configuring timeout on an existing Task using Extension method

I was using SignalR IHubProxy and wanted to configure timeout on the task returned.
The problem is that I didn't create this task and hence couldn't set a timeout using cancellation token, etc
Thanks to the support from SignalR team, I was able to set Timeout using Extension method
Below is the sample code

public static class TaskExtensions
{
    public static async Task<T> TimeoutAfter<T>(this Task<T> task, TimeSpan timeout)
    {
        var delayTask = Task.Delay(timeout);
        var finishedFirst = await Task.WhenAny(task, delayTask);

        if (finishedFirst != delayTask)
        {
            // Task finished before the timeout
            return ((Task<T>)finishedFirst).Result;
        } 

        // Task didn't finish before the timeout
        // Note: Technically the task wasn't canceled at all, it's still running but there's no
        //       way to stop it from here but the caller can handle this exception and retrieve
        //       the task from the InnerException.Task property if further action is desired.
        throw new TaskCanceledException(
            "The task didn't complete within the specified time.",
            new TaskCanceledException(task));
    } 

    private static async void ExampleUsage()
    {
        var exampleAsync = new Func<Task<int>>(() => Task.FromResult(1)); 

        try
        {
            var result = await exampleAsync().TimeoutAfter(TimeSpan.FromSeconds(10));
        }
        catch (TaskCanceledException)
        {
            // The task timed out
        }
    }
}

No comments:

Post a Comment