Imagine that you have a Task handed to you by a third party, and that you would like to force this Task to complete within a specified time period. However, you cannot alter the “natural” completion path and completion state of the Task, as that may cause problems with other consumers of the Task. So you need a way to obtain a copy or “proxy” of the Task that will either (A) complete within the specified time period, or (B) will complete with an indication that it had timed out.

public static async Task TimeoutAfter(this Task task, int millisecondsTimeout)
if (task == await Task.WhenAny(task, Task.Delay(millisecondsTimeout)))
        await task;
throw new TimeoutException();

The implementation above takes advantage of the new async/await support in .NET 4.5, and is pleasingly concise. However, it does lack some optimizations:

  1. The edge cases (when the caller specifies a zero timeout, or an infinite timeout) are not handled well. (But that could probably be fixed.)
  2. A Task is created via Task.Delay, instead of just a simple timer job.
  3. In the cases where the source Task (task) completes before the timeout expires, no effort is made to cancel the internal timer job that was launched in the Task.Delay call. If the number of “zombie” timer jobs starts becoming significant, performance could suffer.

Nevertheless, it is good to consider the use of async/await support in implementing features like this. Often await will be optimized in ways that simple continuations are not.

Another potential implementation of Task.TimeoutAfter with Rx:

public static Task TimeoutAfter(this Task task, int millisecondsTimeout)
return task.ToObservable().Timeout(TimeSpan.FromMilliseconds(millisecondsTimeout)).ToTask();

Read the entire post on Parallel Programming With .NET.


Share your thoughts

Please log in using one of these methods to post your comment: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s