在没有等待的情况下重新排除任务c#中的异常

时间:2015-10-15 10:31:35

标签: c# exception task

我有一个GUI应用程序,我希望在任务中运行某些东西,因此它不会保留UI。我希望将任务中未处理的未处理异常传播到应用程序级异常处理程序。 但是:

  1. 如果我在任务中抛出异常,它将无法达到应用级别 例外,除非我使用wait / await
  2. Async / Await - 我从UI构造函数调用该方法,所以我不能在那里使用async / await,因为我需要继续使用consturction。我只想运行任务而忘记。
  3. 我在考虑使用dispatcher.invoke,你怎么看?

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

2 个答案:

答案 0 :(得分:2)

我能想到的两种方式。首先,注册TaskScheduler.UnobservedTaskException事件并记录您需要的任何内容:

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

由于某种原因你不想使用的更好的选择是实际等待操作并将其包装在try-catch中:

private async Task MyMethodAsync()
{
    try
    {
       await Task.Run(() =>
       {
          // Do some staff
       });
       InvokeContinuation();
    }
    catch (Exception e)
    {
        // Log.
    }
}

答案 1 :(得分:0)

要意识到通过调用Task.Run,​​您通常会产生一个新线程,这可能不是您想要的大部分时间。在某些你正在进行CPU绑定工作的情况下创建新线程是有意义的,在这种情况下,你会考虑利用其他Parallel computation libraries来充分利用它。相反,如果您的工作是I / O绑定,您应该能够一直使用异步调用。

为了等待异步方法调用的结果或异常冒泡到调用点,您可以始终将对ContinueWith的调用添加到异步方法返回的任务中。如果您同时处理结果和任何可能的异常,那么async / await语义工作得很好。但请注意,默认情况下,在这些延续中执行的代码可能不会在与原始线程相同的线程中执行。