我有下面的例子:(请同时阅读代码中的注释,因为这样会更有意义)

public async Task<Task<Result>> MyAsyncMethod()
{
    Task<Result> resultTask = await _mySender.PostAsync();
    return resultTask;

    // in real-life case this returns to a different assembly which I can't change
   // but I need to do some exception handling on the Result in here
}

假设PostAsync的方法如下:
public Task<Task<Result>> PostAsync()
{
  Task<Result> result = GetSomeTask();
  return result;
}

问题是:
因为我不等待mySender中的实际Result,并且如果MyAsyncMethod方法抛出异常,那么将在哪个上下文中抛出和处理异常?

有什么方法可以处理程序集中的异常吗?
当我试图将PostAsync改为:
 public async Task<Task<Result>> MyAsyncMethod()
{
  try
  {
    Task<Result> resultTask = await _mySender.PostAsync();
    return resultTask;
  }
  catch (MyCustomException ex)
  {
  }
}

这里捕获到异常,如果没有等待实际结果,则返回事件。碰巧MyAsyncMethod的结果已经可用,并且在此上下文中引发异常,对吗??
是否可以使用PostAsync处理当前类中的异常?例如:
public async Task<Task<Result>> MyAsyncMethod()
{
    Task<Result> resultTask = await _mySender.PostAsync();
    var exceptionHandlingTask = resultTask.ContinueWith(t => { handle(t.Exception)}, TaskContinuationOptions.OnlyOnFaulted);
    return resultTask;
}

最佳答案

这是许多问题打包成一个单一的“问题”,但好…
如果不等待异步任务,它将在何处引发异常?
未观察到的任务异常由TaskScheduler.UnobservedTaskException事件引发。此事件“最终”引发,因为在认为任务异常未处理之前,必须实际对其进行垃圾收集。
因为我不等待myAsyncMethod中的实际结果,而且如果postAsync方法抛出异常,那么将在哪个上下文中抛出和处理该异常?
任何使用async修饰符并返回Task的方法都会将其所有异常放在返回的Task上。
有什么方法可以处理程序集中的异常吗?
是的,您可以替换返回的任务,例如:

async Task<Result> HandleExceptionsAsync(Task<Result> original)
{
  try
  {
    return await original;
  }
  catch ...
}

public async Task<Task<Result>> MyAsyncMethod()
{
  Task<Result> resultTask = await _mySender.PostAsync();
  return HandleExceptionsAsync(resultTask);
}

当我试图将myAsyncMethod更改为[同步返回内部任务]时,即使没有等待实际结果,这里也捕获到异常。
这实际上意味着,正如您的代码示例所示,您调用的方法不是async Task。它是一个非-asyncTask返回的方法,当其中一个方法抛出异常时,它的处理方式与任何其他异常一样(即,它直接向上传递调用堆栈,而不是放在返回的Task上)。
是否可以使用continueWith处理当前类中的异常?
是的,但是await更干净。

关于c# - 如果异步任务未等待,它将在哪里引发异常?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25691114/

10-11 22:46
查看更多