简体   繁体   English

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

[英]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. 我有一个GUI应用程序,我想在一个任务中运行一些东西,所以它不会保存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 如果我只是在任务中抛出异常,它将无法达到应用程序级异常,除非我使用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. Async / Await - 我从UI构造函数调用该方法,因此我不能在那里使用async / await,因为我需要继续使用consturction。 I just want to run the task and forget. 我只想运行任务而忘记。

I was thinking about using dispatcher.invoke, what do you think? 我在考虑使用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);
    }
}

Two ways I can think of. 我能想到两种方式。 First, is register to TaskScheduler.UnobservedTaskException event and log whatever you need there: 首先,注册到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);
}

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 : 由于某种原因你不想使用的更好的选择是实际等待操作并将其包装在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. 要意识到通过调用Task.Run,​​您通常会产生一个新线程,这可能不是您想要的大多数时间。 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. 在某些你正在进行CPU绑定工作的情况下创建新线程是有意义的,在这种情况下,你需要考虑利用其他并行计算库来充分利用它。 Instead if your work is I/O bound you should be able to use asynchronous calls all the way down. 相反,如果您的工作是I / O绑定,您应该能够一直使用异步调用。

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. 为了等待异步方法调用的结果或异常冒泡到调用点,您可以始终将对ContinueWith的调用添加到异步方法返回的任务。 If you are handling both the result and any possible exceptions then async/await semantics work nice. 如果您同时处理结果和任何可能的异常,那么async / await语义工作得很好。 Note however that the code that executes in these continuations may not execute in the same thread as the original thread by default. 但请注意,默认情况下,在这些延续中执行的代码可能不会在与原始线程相同的线程中执行。

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

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