Do a long process with a task and showing an exception if there is one
I am testing using Task in my application. Now I have done the following:
var task = Task.Factory.StartNew(() => {
// long running process
throw new Exception("test"); // throwing TestException
});
task.ContinueWith(x => MyErrorHandler(task.Exception), TaskContinuationOptions.OnlyOnFaulted);
void MyErrorHandler(Exception error) {
MessageBox.Show(error.Message);
}
The idea is that the lengthy process will be done and the user can work without any blocking of the user interface. If there is a problem (exception), it will be shown after the end of the lengthy process (in the usual case, there will be no exception)
Did I use it correctly or do I need to do it differently? Are there any problems I might get along the way that I can't see now?
source to share
This will work since you are explicitly checking Task.Exception
what will prevent the exception from being hidden.
I would make a couple of recommendations here.
First, if this is a really long task, you can point out that:
var task = Task.Factory.StartNew(() => {
// long running process
throw new Exception("test"); // throwing TestException
}, TaskCreationOptions.LongRunning);
Second, you don't need to close over task
:
// use x.Exception, since x is the task
task.ContinueWith(x => MyErrorHandler(x.Exception), TaskContinuationOptions.OnlyOnFaulted);
You may also want to do this launch on the main thread, especially if you decide you want to use something more complex (in your interface) to post:
// This will work if MyErrorHandler uses a UI control, since it'll marshal back to the current synchronization context
task.ContinueWith(x => MyErrorHandler(x.Exception),
CancellationToken.None,
TaskContinuationOptions.OnlyOnFaulted,
TaskScheduler.FromCurrentSynchronizationContext());
(This is only required if you intend to use UI controls, etc., in an error handler.)
Also - if you are using .NET 4.5 or the .NET 4 asynchronous targeting package, you can simplify this by using the new support for async
/ await
. If you specify your method as async
, you can do:
try
{
await Task.Factory.StartNew(() => {
// long running process
throw new Exception("test"); // throwing TestException
}, TaskCreationOptions.LongRunning);
}
catch(Exception error)
{
MyErrorHandler(error);
}
source to share