同步使用异步时捕获原始异常

时间:2016-01-14 15:43:30

标签: c# locking async-await

我正在使用PCLStorage库来访问多个平台上的文件。 该库仅提供异步方法。我在lock块中使用这些方法,以便它们可以同步运行。我正在使用.Result等待调用结果。我试图在这个锁中捕获异常,但因为AggregateException被抛出,它将不会到达我的catch块。

lock (this)
{
    try
    {
        IFile file = folder.GetFileAsync (FileName).Result;
    }
    catch (FileNotFoundException)
    {
        //won't be catched
    }
}

如何在lock内找到原始异常?

2 个答案:

答案 0 :(得分:3)

要在等待Task完成时阻止当前线程,并获取解包的Task异常(如果有),您可以执行以下操作:

try
{
    var file = folder.GetFileAsync(FileName).GetAwaiter().GetResult();
}
catch (FileNotFoundException)
{
    // Will be catched :)
}

如果您阻止.Result属性,则需要捕获AggregateExcetpion并检查其内部异常。

要获得更多相关信息,我可以在A Tour of Task上推荐Stephen Cleary的博客系列。在Part 6: Results,他写道:

  

<强> Result   与Wait一样,Result将同步阻止调用线程,直到任务完成。 (...)此外,Result将换行   AggregateException内的任何任务异常。这通常只是   使错误处理变得复杂。

     

GetAwaiter().GetResult() {4.5}中的GetAwaiter成员已添加到TaskTask<T>,并且可以作为扩展方法使用   .NET 4.0使用Microsoft.Bcl.Async NuGet包。 (...)在   一般来说,我尽量避免同步阻止   异步任务。但是,我有几种情况   确实违反了该准则。在那些罕见的情况下,我的首选   方法是GetAwaiter().GetResult() ,因为它保留了任务   异常,而不是将它们包装在AggregateException

答案 1 :(得分:1)

  

如何在锁定内部时捕获原始异常?

你没有。您必须捕获聚合异常,解包它,并查看内部异常是什么。如果这是你无法处理的异常,那么你总是可以重新抛出它。

  

我在lock块中使用这些方法,因此它们可以异步运行

使用lock不会使其异步。最重要的是,你同步阻止它,所以你甚至没有这样做。这句话完全没有意义。