Showing posts with label extension method. Show all posts
Showing posts with label extension method. Show all posts

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
        }
    }
}