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

本文关键字:原始 异常 异步 同步 | 更新日期: 2023-09-27 18:30:28

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

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

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

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

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

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

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

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

Result Wait 一样,Result 将同步阻塞调用线程,直到任务完成。(...)此外,Result将包装 AggregateException内的任何任务异常。这通常只是 使错误处理复杂化。

GetAwaiter().GetResult() GetAwaiter成员已添加到 .NET 4.5 中的TaskTask<T>中,它可作为扩展方法 使用 Microsoft.Bcl.Async NuGet 包的 .NET 4.0。(...) 在 一般,我尽力避免同步阻塞 异步任务。但是,在少数情况下,我 确实违反了该准则。在那些罕见的情况下,我更喜欢 方法GetAwaiter().GetResult(),因为它保留了任务 例外而不是将它们包装在AggregateException中。

如何捕获在锁内抛出的原始异常?

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

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

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