Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do long running process with Task and showing Exception if there is one

I am testing for using Task in my application. Now, I have done the fallowing:

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 long running process will executed and the user can working on without any blocking of the UI. If there was a problem (exception) it will be show, after the long running process has finished (in the normal case, there would be no exception)

Is this the correct way I have used it or does I have to do it on another way? Are there any problems, which I can get on this way and I don't see now?

like image 323
BennoDual Avatar asked Feb 18 '23 13:02

BennoDual


1 Answers

This will work, as you're explicitly checking Task.Exception, which will prevent the exception from being unobserved.

I would make a couple of recommendations here.

First, if this is truly a long running task, you might want to specify that:

var task = Task.Factory.StartNew(() => {
   // long running process
   throw new Exception("test"); // throwing TestException
}, TaskCreationOptions.LongRunning);

Second, you don't need the closure over task:

// use x.Exception, since x is the task
task.ContinueWith(x => MyErrorHandler(x.Exception), TaskContinuationOptions.OnlyOnFaulted);

You may also want to have this run on the main thread, especially if you decide you want to use something more elaborate (in your UI) for reporting:

// 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're going to use UI controls, etc, in your error handler.)

Also - If you're using .NET 4.5 or the async targetting pack for .NET 4, you can simplify this by using the new async/await support. If you flag 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);
}
like image 137
Reed Copsey Avatar answered Feb 20 '23 12:02

Reed Copsey