Asynchronous programming is hard. Because it’s so difficult, developers are constantly trying to find ways to make it simpler, whether it’s promises or callbacks, or the async/await pattern. It gets more difficult when you need to deal with handling exceptions- when a task fails, trying to recover from that failure in a separate thread is an extra special challenge.

Which brings us to Betty’s co-worker. Using C#’s Task objects, which tie into the async/await pattern, they wanted to simply ignore any exceptions thrown by one of those tasks. That’s your first WTF, of course. Their approach, however, is a larger one:

public static void Forget(this Task task)
{
    task.ContinueWith(task2 =>
        {
            try
            {
                task.Wait();
            }
#pragma warning disable 168
            catch (Exception ex)
#pragma warning restore 168
            {
                // ignored
            }
        }).ConfigureAwait(false);
}

First, let’s talk about ContinueWith. ContinueWith is meant as a continuation for a task. By continuation, of course, we mean after the original task has finished. So, our very first line here starts by saying, “When the task (which may have thrown uncaught exceptions) has finished, start a new task”. The goal of catching unhandled exceptions has already left the building.

So what do we do in our second task (the lambda passed to ContinueWith)? Why, we wait on the original task to complete. As stated, our second task won’t start until the original task has completed, so calling Wait does nothing.

Well, not entirely nothing. If the original task had an exception and entered a faulted state, Waiting on that task… throws a new exception. Which we fortunately have a catch block to handle. And ignore. Helpful #pragmas conceal the compiler warnings for that overly broad catch block, which tells me this developer is a pro at ignoring compiler warnings.

The best part, though, is the comment on this method. Which I left out, to save for last.

/// <summary>
/// Strongly unrecommended unless you are certain all
/// exceptions are eaten.
/// </summary>
/// <param name="task"></param>

I strongly unrecommend this code. I don’t care how many exceptions you eat, don’t use this code.

[Advertisement] ProGet supports your applications, Docker containers, and third-party packages, allowing you to enforce quality standards across all components. Download and see how!