简体   繁体   中英

Rethrowing exceptions in tasks c# without wait

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:

  1. If I just throw an exception in the task it will not reach app level exceptions unless I use wait/await
  2. Async/Await - I call the method from a UI constructor, so I can't use async/await there, since I need to continue with the consturction. I just want to run the task and forget.

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);
    }
}

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.
    }
}

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM