To some extent, it's a matter of preference, especially if you 'own' the task code and the calling code. Here are some things to consider.
Firstly, you should only catch exceptions that you know how to handle. This applies whether you handle them with a continuation or with a try/catch inside the action.
Note also the changed behaviour in .NET 4.5 regarding uncaught exceptions. The change is effecitvely from the 'purist' approach (tear down the process on an uncaught task exception) to a less draconian one. Still, it's not good deliberately to rely on the new behaviour.
As for which of your two alternatives to favour, there is an argument for choosing the second one: handling the exception in a continuation. It will be increasingly common in .NET for methods to return a Task
. For example, Stream.ReadAsync. To use such methods correctly you need a continuation (either the conventional way, or using a try/catch block with the new await
feature, which amounts to the same thing, but is much easier to code and read). So it's good to get into the habit of assuming that any Task
may fail unless you explicitly know otherwise, and coding appropriate exception handling behavior.
In case you're interested, here is an alternative way of coding your second example in .NET 4.5.
async Task MyMethod()
{
try
{
await Task.Run(
() =>
{
// Some work.
});
}
catch (SomeException ex)
{
}
}
Another difference most frequently applies in Windows Forms or WPF applications where your code is called from the UI thread. Here the default behaviour of the TPL when using await
is to run continuations using a synchronization context that marshals them back to the UI thread. That is, if your Task.Run
is called from the UI thread, the continuation will also run on the UI thread.
This is useful if you want to display a dialog to the user in response to an exception. You would not be able to do that successfully from within the Task
worload. When using explicit continutations rather than await
, you must pass a TaskScheduler
created using TaskScheduler.FromCurrentSynchronizationContext to the appropriate overload of ContinueWith.