我有下面的例子:(请同时阅读代码中的注释,因为这样会更有意义)
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
。它是一个非-async
,Task
返回的方法,当其中一个方法抛出异常时,它的处理方式与任何其他异常一样(即,它直接向上传递调用堆栈,而不是放在返回的Task
上)。是否可以使用continueWith处理当前类中的异常?
是的,但是
await
更干净。关于c# - 如果异步任务未等待,它将在哪里引发异常?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25691114/