繁体   English   中英

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

[英]Rethrowing exceptions in tasks c# without wait

我有一个GUI应用程序,我想在一个任务中运行一些东西,所以它不会保存UI。 我希望将任务中未处理的未处理异常传播到应用程序级异常处理程序。 然而:

  1. 如果我只是在任务中抛出异常,它将无法达到应用程序级异常,除非我使用wait / await
  2. Async / Await - 我从UI构造函数调用该方法,因此我不能在那里使用async / await,因为我需要继续使用consturction。 我只想运行任务而忘记。

我在考虑使用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);
    }
}

我能想到两种方式。 首先,注册到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.
    }
}

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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