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

Waa*_*als 0 c# locking async-await

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

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

如何捕获内部抛出的原始异常lock

Las*_*sen 5

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

\n\n
try\n{\n    var file = folder.GetFileAsync(FileName).GetAwaiter().GetResult();\n}\ncatch (FileNotFoundException)\n{\n    // Will be catched :)\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

要获得更多这方面的信息,我可以推荐 Stephen Cleary 的博客系列 A Tour of Task。在第 6 部分:结果中,他写道:

\n\n
\n

Result\n 与 一样WaitResult将同步阻塞调用线程直到任务完成。(...)此外,Result会将任何任务异常包装在AggregateException. 这通常只会使错误处理变得复杂。

\n\n

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

\n
\n