Reputation: 121
I have a GUI application, in which I want to run something in a task, so it will not hold the UI. I want un unhandled exception in the task to be propogated to the application level exception handler. However:
I was thinking about using dispatcher.invoke, what do you think?
public MainWindow()
{
InitializeComponent();
MyMethodAsync();
InitializeA();
IntiializeB();
}
private void MyMethodAsync()
{
Task t = Task.Run(() =>
{
//Do some stuff
throw new Exception("Throwing some unexpected exception");
}).ContinueWith(MyContinueWith);
}
private void MyContinueWith(Task task)
{
if (task.IsFaulted && task.Exception != null)
{
dispatcher.BeginInvoke(new Action(() =>
{
throw task.Exception;
}), null);
}
}
Upvotes: 4
Views: 1152
Reputation: 17356
Do realize that by calling Task.Run you are generally spawning a new thread which is not likely what you want most of the time. Creating new threads makes sense in some instances where you are doing CPU bound work and in those cases you'll want to consider leveraging other Parallel computation libraries to get the most out of it. Instead if your work is I/O bound you should be able to use asynchronous calls all the way down.
In order to wait for the result of a async method call or an exception bubbled up to the call point you can always tack on a call to ContinueWith to the a task that is returned by the async method. If you are handling both the result and any possible exceptions then async/await semantics work nice. Note however that the code that executes in these continuations may not execute in the same thread as the original thread by default.
Upvotes: 0
Reputation: 149538
Two ways I can think of. First, is register to TaskScheduler.UnobservedTaskException
event and log whatever you need there:
private void MyMethodAsync()
{
// Note you should probably register only once, so this may not fit here.
TaskScheduler.UnobservedTaskException += (s, e) => GlobalLogger.Log(e);
Task t = Task.Run(() =>
{
// Do some staff
}).ContinueWith(MyContinueWith);
}
The better option which for some reason you don't want to use, is to actually await the operation and wrap it in a try-catch
:
private async Task MyMethodAsync()
{
try
{
await Task.Run(() =>
{
// Do some staff
});
InvokeContinuation();
}
catch (Exception e)
{
// Log.
}
}
Upvotes: 2