Share via


Task-based Asynchronous Pattern - WaitAsync

Recently I was asked about a specific scenario when some code was being converted into using TAP and this was code that already used tasks. Since the existing code used the "IsFaulted" property a lot I came up with this little extension method making it easy to see if a task failed or not using the await keyword but without adding a lot of exception handling.

  1: public static Task<bool> WaitAsync(this Task task)
 2: {
 3:     var tcs = new TaskCompletionSource<bool>();
 4:     task.ContinueWith(
 5:         t => tcs.TrySetResult(!(t.IsFaulted || t.IsCanceled)));
 6:     return tcs.Task;
 7: }

So why avoid exceptions? Well I think that is a separate topic but a few short observations; exceptions have some performance penalties so you don't want to use them for common errors and some people think exceptions make it harder to follow the flow of the code. Whatever you think about all that I think you'll find the WaitAsync method useful more or less often.

Comments

  • Anonymous
    January 06, 2013
    Try this one out for better perf: public static Task<bool> WaitAsync(this Task task) { return task.ContinueWith( t => !(t.IsFaulted || t.IsCanceled), TaskContinuationOptions.ExecuteSynchronously); } However, this will still have a penalty, while a non-throwing await will not have any. An odd tradeoff you're making here that makes me wonder -- are exceptions not being used only for truly exception cases?

  • Anonymous
    January 07, 2013
    @Cory; I've seen projects that did use Exceptions for general error handling. There are also plenty of cases where you use a library that throws but you consider it to be a non-exceptional case. File.Open is probably the most famous example since I might be using it in a scenario where FileNotFound is pretty common and not an exceptional case.