Timeout pattern on task-based asynchronous method in C#

前端 未结 2 1048
故里飘歌
故里飘歌 2020-12-03 04:01

As far as I know, there\'re two possible patterns to implement a timeout to task-based asynchronous methods:

Built-in timeout

public Task DoStuffAs         


        
2条回答
  •  甜味超标
    2020-12-03 04:24

    While you can reuse WithCancellation for both cancellations and timeouts I think it's an overkill for what you need.

    A simpler and clearer solution for an async operation timeout would be to await both the actual operation and a timeout task using Task.WhenAny. If the timeout task completes first, you got yourself a timeout. Otherwise, the operation completed successfully:

    public static async Task WithTimeout(this Task task, TimeSpan timeout)
    {
        if (task == await Task.WhenAny(task, Task.Delay(timeout)))
        {
            return await task;
        }
        throw new TimeoutException();
    }
    

    Usage:

    try
    {
        await DoStuffAsync().WithTimeout(TimeSpan.FromSeconds(5));
    }
    catch (TimeoutException)
    {
        // Handle timeout.
    }
    

    If you prefer to not throw an exception (as I do) it's even simpler, just return the default value:

    public static Task WithTimeout(this Task task, TimeSpan timeout)
    {
        var timeoutTask = Task.Delay(timeout).ContinueWith(_ => default(TResult), TaskContinuationOptions.ExecuteSynchronously);
        return Task.WhenAny(task, timeoutTask).Unwrap();
    }
    

提交回复
热议问题