呼叫等待GetFileAsync()永远不会返回,并在应用程序WinRT中挂起 [英] Call to await GetFileAsync() never returns and app hangs in WinRT app
问题描述
我试图加载和读取设置在应用程序启动文件,时间大约90%,在等待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.
关于有四分之一的时间,如果我通过code步骤,它会返回实际上并读取该文件。
About a quarter of the time, if I step through the code, it'll actually return and read the file.
这里的code的一个简化版本:
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 Output窗口,经过一段时间的等待,我得到线程'<没有名称>' (0x30c)已退出与code 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
A 工作
一个尚未完成,则该方法继续在捕获的上下文(在这种情况下,在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).
所以,在这里就是为什么你的code失败:
So, here's why your code is failing:
-
OnLaunched
要求加载
(用户界面范围内)。 -
加载
等待。这将导致加载
方法返回一个不完整的任务,并计划建成供以后使用。这延续定于UI环境。 -
OnLaunched
阻止加载
返回。这将阻止UI线程。 -
GetFileAsync
最终完成,并尝试运行加载
的延续。 - 为
加载
的继续等待UI线程可用,因此它可以在UI上下文中执行的。 - 在这一点上,<code> OnLaunched 正在载入等
来完成(这样做阻塞UI线程)和
加载
正在等待UI线程是免费的。僵局。
在任务
OnLaunched
callsLoad
(within the UI context).Load
awaits. This causes theLoad
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 fromLoad
. This blocks the UI thread.GetFileAsync
eventually completes, and attempts to run the continuation forLoad
.- 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 forLoad
to complete (blocking the UI thread by doing so), andLoad
is waiting for the UI thread to be free. Deadlock.
这些最佳实践避免出现这种情况:
These best practices avoid this situation:
- 在库
异步
方法,使用ConfigureAwait(假)
只要有可能。在你的情况,这将改变等待folder.GetFileAsync(filename.xml中);
到等待folder.GetFileAsync(filename.xml中) .ConfigureAwait(假);
。 - 请不要在
工作
S挡;这是异步
一路下跌。换句话说,替换等待
与等待
。
- In your "library"
async
methods, useConfigureAwait(false)
whenever possible. In your case, this would changeawait folder.GetFileAsync("filename.xml");
toawait folder.GetFileAsync("filename.xml").ConfigureAwait(false);
. - Don't block on
Task
s; it'sasync
all the way down. In other words, replaceWait
withawait
.
有关详细信息:
- 等待和UI,和死锁!哦,我的!
- 我的<一个href=\"http://nitoprograms.blogspot.com/2012/02/async-and-await.html\"><$c$c>async$c$c>/<$c$c>await$c$c>介绍后,其中包括
工作
awaiters如何使用的SynchronizationContext
的简要说明,并介绍了一些最佳实践。 - /等待FAQ ,该进入详细在上下文中。
- 这<一个href=\"http://social.msdn.microsoft.com/Forums/en-AU/async/thread/269172a3-adb9-4b5e-9ac1-8b67ff920177\">MSDN论坛帖子。
- 斯蒂芬Toub 演示这一僵局和<一个href=\"http://blogs.msdn.com/b/lucian/archive/2012/03/29/talk-async-part-1-the-message-loop-and-the-task-type.aspx\">so确实卢西恩Wischik 。
- Await, and UI, and deadlocks! Oh, my!
- My
async
/await
intro post, which includes a brief description of howTask
awaiters useSynchronizationContext
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-07-13:将这一答案的成博客文章。
这篇关于呼叫等待GetFileAsync()永远不会返回,并在应用程序WinRT中挂起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!