呼叫等待GetFileAsync()永远不会返回,并应用在WinRT的应用程序挂起(Call to

2019-06-26 00:25发布

我试图加载和读取应用程序启动一个设置文件,时间大约90%,在await GetFileAsync("filename.xml"); 永远不会返回,因此,悬挂应用。

关于有四分之一的时间,如果我通过代码,它会实际上将返回并阅读该文件。

下面的代码的一个非常简化的版本:

App.xaml.cs:

protected override void OnLaunched(LaunchActivatedEventArgs args)
{
    FileLoader.Load().Wait();

    // File-load dependent stuff
}

FileLoader.cs:

public async static Task Load()
{
    StorageFolder folder = ApplicationData.Current.LocalFolder;
    StorageFile file;
    bool fileExists = true;

    try
    {
        // The following line (often) never returns
        file = await folder.GetFileAsync("filename.xml");
    {
    catch
    {
        fileExists = false;
    }

    // Do stuff with loaded file
}

如果我看的输出窗口在Visual Studio中,经过一段时间的等待,我得到"The thread '<No Name>' (0x30c) has exited with code 0 (0x0)."

有没有人有这里发生了什么的任何想法?

Answer 1:

默认情况下,当你await一个Task是尚未完成,该方法继续在捕捉的上下文(在这种情况下,UI方面)。

所以,在这里就是为什么你的代码是失败:

  • OnLaunched呼叫Load (在UI范围内)。
  • Load等待。 这将导致Load方法返回一个未完成的任务,并安排其完成供以后使用。 这是继续安排在UI方面。
  • OnLaunched的任务阻止返回Load 。 这将阻止UI线程。
  • GetFileAsync最终完成,并尝试运行延续Load
  • 为延续Load等待UI线程可用,以便它可以在UI上下文中执行的。
  • 在这一点上, OnLaunched正在等待Load完成(通过这样做阻塞UI线程),并Load在等待UI线程是免费的。 僵局。

这些最佳实践避免出现这种情况:

  1. 在您的“库” async方法,使用ConfigureAwait(false)只要有可能。 在你的情况,这将改变await folder.GetFileAsync("filename.xml");await folder.GetFileAsync("filename.xml").ConfigureAwait(false);
  2. 不要挡住Task S; 它的async一路下跌。 换句话说,顶替Waitawait

欲获得更多信息:

  • 等待,和UI,和死锁! 天啊!
  • 我的async / await开场后 ,其中包括如何简要说明Task awaiters使用SynchronizationContext ,并介绍了一些最佳做法。
  • 在异步/等待FAQ ,其中进入的背景下更详细。
  • 这MSDN论坛的帖子 。
  • 斯蒂芬Toub 演示这一僵局 ,并因此确实卢西恩Wischik 。

更新,2012-07-13:成立这个答案到博客中 。



文章来源: Call to await GetFileAsync() never returns and app hangs in WinRT app