C# 调用wait GetFileAsync()将永远不会返回,并且应用程序将挂起在WinRT应用程序中
我试图在应用程序启动时加载和读取一个设置文件,C# 调用wait GetFileAsync()将永远不会返回,并且应用程序将挂起在WinRT应用程序中,c#,file-io,windows-8,windows-runtime,async-await,C#,File Io,Windows 8,Windows Runtime,Async Await,我试图在应用程序启动时加载和读取一个设置文件,等待GetFileAsync(“filename.xml”)永不返回,因此挂起应用程序 大约有四分之一的时间,如果我单步执行代码,它实际上会返回并读取文件 下面是代码的一个非常简化的版本: App.xaml.cs: protected override void OnLaunched(LaunchActivatedEventArgs args) { FileLoader.Load().Wait(); // File-load dep
等待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中查看输出窗口,等待一段时间后,我会得到“线程”(0x30c)已退出,代码为0(0x0)。”
有人知道这里发生了什么吗?默认情况下,当您等待尚未完成的
任务时,该方法将在捕获的上下文(在本例中为UI上下文)上恢复
下面是代码失败的原因:
OnLaunched
调用Load
(在UI上下文中)
加载
等待。这会导致Load
方法返回一个未完成的任务,并将其完成时间安排在以后。此延续是为UI上下文安排的
OnLaunched
对从Load
返回的任务执行块。这将阻止UI线程
GetFileAsync
最终完成,并尝试运行Load
的延续
Load
的continuation将等待UI线程可用,以便它可以在UI上下文中执行
- 此时,
OnLaunched
正在等待Load
完成(通过这样做阻止UI线程),而Load
正在等待UI线程释放。僵局
这些最佳做法避免了这种情况:
在“库”async
方法中,尽可能使用ConfigureAwait(false)
。在您的情况下,这将改变await folder.GetFileAsync(“filename.xml”)
toawait folder.GetFileAsync(“filename.xml”).ConfigureAwait(false)代码>
不要阻塞任务
s;它一直是异步的。换句话说,将Wait
替换为Wait
有关更多信息:
- My,其中简要介绍了
任务
等待者如何使用同步上下文
,并介绍了一些最佳实践
- 第二部分,详细介绍了上下文
- 这个
- Stephen Toub和
更新,2012-07-13:包含了这个答案。您正在通过调用等待来阻止UI线程。那真是个坏主意。见鬼,这甚至可能是导致问题的原因。我认为Jon完全正确-您是否有可能将OnLaunched标记为async,然后等待Load()调用?如果不能,那么另一种方法可能是让Load在加载完成后执行一个操作,然后在最后运行该操作(或者,当然,您可以在Load()返回的任务上使用ContinueWith,就像在async/Wait:之前一样)。Jon和James,您都是对的。非常感谢您的投入!我最初使用的是Wait
,因为我没有意识到可以将async
添加到重写的方法中,而且我不知道OnLaunched
正在UI线程上运行。删除Wait
并将async
添加到OnLaunched
修复了它!我希望我能把你的评论作为答案。很好的答案!非常感谢您对正在发生的事情的详细解释和参考文章的广泛列表。这让一切都更清楚了,这太完美了。这让我省去了太多的悲伤,真是难以置信。我希望MS死了。因为提供了这些疯狂的东西,他们肯定是在找人。他们为什么不留下老式的线程和同步原语?!笨蛋。@AlekDepler:。虽然您可以使用线程“伪造”一些异步编程,但您不能总是使用线程来解决异步编程需求。我可以,我也可以。“假”是微软每年发明的轮子。目前,我在WPF中唯一需要的是简单线程。疲倦的