调用 await GetFileAsync() 永远不会返回,并且应用程序在 WinRT 应用程序中挂起

Call to await GetFileAsync() never returns and app hangs in WinRT app(调用 await GetFileAsync() 永远不会返回,并且应用程序在 WinRT 应用程序中挂起)
本文介绍了调用 await GetFileAsync() 永远不会返回,并且应用程序在 WinRT 应用程序中挂起的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm attempting to load and read a settings file on application launch, and about 90% of the time, the await GetFileAsync("filename.xml"); never returns, thus, hanging the application.

大约四分之一的时间,如果我单步执行代码,它实际上会返回并读取文件.

About a quarter of the time, if I step through the code, it'll actually return and read the file.

这是一个非常简化的代码:

Here's a very simplified version of the code:

App.xaml.cs:

App.xaml.cs:

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

    // File-load dependent stuff
}

FileLoader.cs:

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) 已退出,代码为 0 (0x0)."

If I watch the Output window in Visual Studio, after awhile of waiting I get "The thread '<No Name>' (0x30c) has exited with code 0 (0x0)."

有人知道这里发生了什么吗?

Does anyone have any idea of what's happening here?

推荐答案

默认情况下,当你 await 一个尚未完成的 Task 时,方法会在捕获的上下文(在本例中为 UI 上下文).

By default, when you await a Task that has not yet completed, the method resumes on a captured context (in this case, the UI context).

所以,这就是您的代码失败的原因:

So, here's why your code is failing:

  • OnLaunched 调用 Load(在 UI 上下文中).
  • 加载等待.这会导致 Load 方法返回一个未完成的任务并安排其完成以供以后使用.此延续计划针对 UI 上下文.
  • OnLaunched 阻塞从 Load 返回的任务.这会阻塞 UI 线程.
  • GetFileAsync 最终完成,并尝试运行 Load 的延续.
  • Load 的延续等待 UI 线程可用,以便它可以在 UI 上下文中执行.
  • 此时,OnLaunched 正在等待 Load 完成(这样做会阻塞 UI 线程),而 Load 正在等待UI 线程是空闲的.死锁.
  • OnLaunched calls Load (within the UI context).
  • Load awaits. This causes the Load method to return an incomplete task and schedule its completion for later. This continuation is scheduled for the UI context.
  • OnLaunched blocks on the task returned from Load. This blocks the UI thread.
  • GetFileAsync eventually completes, and attempts to run the continuation for Load.
  • The continuation for Load waits for the UI thread to be available so it can execute in the UI context.
  • At this point, OnLaunched is waiting for Load to complete (blocking the UI thread by doing so), and Load is waiting for the UI thread to be free. Deadlock.

这些最佳做法可以避免这种情况:

These best practices avoid this situation:

  1. 在您的库"async 方法中,尽可能使用 ConfigureAwait(false).在您的情况下,这会将 await folder.GetFileAsync("filename.xml"); 更改为 await folder.GetFileAsync("filename.xml").ConfigureAwait(false);.
  2. 不要阻塞 Tasks;它一直是 async .换句话说,将 Wait 替换为 await.
  1. In your "library" async methods, use ConfigureAwait(false) whenever possible. In your case, this would change await folder.GetFileAsync("filename.xml"); to await folder.GetFileAsync("filename.xml").ConfigureAwait(false);.
  2. Don't block on Tasks; it's async all the way down. In other words, replace Wait with await.

更多信息:

  • 等待,UI,还有死锁!天哪!
  • 我的 async/await 简介帖子,其中简要介绍了Task等待者如何使用SynchronizationContext,并介绍了一些最佳实践.
  • Async/Await 常见问题解答,更详细在上下文中.
  • 此MSDN 论坛帖子.
  • Stephen Toub 演示了这个死锁,以及Lucian Wischik也是如此.
  • Await, and UI, and deadlocks! Oh, my!
  • My async/await intro post, which includes a brief description of how Task awaiters use SynchronizationContext and introduces some best practices.
  • The Async/Await FAQ, which goes into more detail on the contexts.
  • This MSDN forum post.
  • Stephen Toub demos this deadlock, and so does Lucian Wischik.

2012 年 7 月 13 日更新: 包含此答案 写入博客文章.

这篇关于调用 await GetFileAsync() 永远不会返回,并且应用程序在 WinRT 应用程序中挂起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

DispatcherQueue null when trying to update Ui property in ViewModel(尝试更新ViewModel中的Ui属性时DispatcherQueue为空)
Drawing over all windows on multiple monitors(在多个监视器上绘制所有窗口)
Programmatically show the desktop(以编程方式显示桌面)
c# Generic Setlt;Tgt; implementation to access objects by type(按类型访问对象的C#泛型集实现)
InvalidOperationException When using Context Injection in ASP.Net Core(在ASP.NET核心中使用上下文注入时发生InvalidOperationException)
LINQ many-to-many relationship, how to write a correct WHERE clause?(LINQ多对多关系,如何写一个正确的WHERE子句?)