申请被"等待"?

时间:2016-05-15 20:44:13

标签: c# asynchronous winrt-xaml

我使用异步方法作为StorageFile的扩展名来返回文件的大小。问题是,这种方法以某种方式死锁我的Windows应用商店应用。问题正在等待来自file.GetBasicPropertiesAsync的结果。我在异步编程方面不是很有经验,但我认为await语句是为了防止这种情况。有没有人看到一些我不明白的东西?

如果我用GetBasicPropertiesAsync等待一段时间,调试中不会发生死锁。

方法:

    public static async Task<string> GetSizeMB(this StorageFile file)
    {
        var properties = await file.GetBasicPropertiesAsync();
        double sizeDouble = Convert.ToDouble(properties.Size) /1000000;

        return $"{Math.Round(sizeDouble, 2)} MB";
    }

提前感谢提示。

1 个答案:

答案 0 :(得分:1)

如果您进一步查看调用堆栈,您几乎肯定会从UI线程调用任务ResultWait成员。 Windows Store应用程序不允许这样做,因为它可以冻结UI线程。

我在博客上详细描述了this kind of deadlock,但摘要版本如下:

await必须(异步)等待时,默认情况下它将首先捕获&#34;上下文&#34;。这个&#34;上下文&#34;是SynchronizationContext.Current,除非它是null,在这种情况下它是TaskScheduler.Current。稍后,当(异步)等待完成时,async方法的剩余部分将继续在捕获的上下文上执行

在这种情况下,上下文是UI SynchronizationContext。进一步调用堆栈,另一种方法调用GetSizeMB并返回一个任务,然后(可能)调用该任务的ResultWait。这是死锁的实际原因,因为该代码在GetSizeMB完成之前阻塞 UI线程。但是GetSizeMB无法完成,因为它需要在UI线程上继续执行。

正确的解决方法是将Result / Wait替换为await