FileIO.ReadTextAsync 偶尔会挂起
本文关键字:挂起 偶尔 ReadTextAsync FileIO | 更新日期: 2023-09-27 18:34:51
我只是在试验WinRT,我正在创建的一个演示应用程序是一个基本的"记事本"风格的应用程序,可以加载/保存到本地存储。虽然我熟悉构建 WinRT 应用的正确async
方法,但我的演示应用正在使用同步Load
来简化操作。
问题是,当调用 Load
,它工作 2 次中的 3 次,其余时间应用程序挂在呼叫上var result = await FileIO.ReadTextAsync(storageFile);
public class ContentStorage : IContentStorage
{
private const string FileName = "contents.txt";
public string Load()
{
return LoadAsync().Result;
}
public void Save(string content)
{
SaveAsync(content);
}
private static async Task<string> LoadAsync()
{
var storageFile = await LocalFolder.GetFileAsync(FileName);
var result = await FileIO.ReadTextAsync(storageFile);
return result;
}
private static async void SaveAsync(string content)
{
var storageFile = await LocalFolder.CreateFileAsync(FileName, CreationCollisionOption.ReplaceExisting);
FileIO.WriteTextAsync(storageFile, content);
}
private static StorageFolder LocalFolder
{
get { return ApplicationData.Current.LocalFolder; }
}
}
我在这里做了什么非常愚蠢的事情吗?
FWIW,我尝试将Load
更改为在每个步骤上显式阻止,这将悬挂提高到 1/20,但我仍然不明白为什么它会挂起......
public string Load()
{
var storageFile = LocalFolder.GetFileAsync(FileName).AsTask().Result;
var result = FileIO.ReadTextAsync(storageFile).AsTask().Result;
return result;
}
虽然我熟悉构建 WinRT 应用的正确
async
方法,但我的演示应用正在使用同步Load
来简化操作。
没有。将同步代码与异步代码混合在一起非常复杂。在任何地方使用async
要简单得多。
当 async
方法在等待任务后继续执行时,默认情况下它将返回到其原始上下文。(我在async
/await
博客文章中更详细地介绍了这一点(。某些上下文(例如 UI 上下文(仅允许单个线程;如果该线程被阻塞(例如,在 Task.Result
上(,则 async
方法无法进入该上下文以完成其执行。这会导致死锁。
欲了解更多信息:
async
/await
常见问题解答有很多关于上下文捕获和恢复的详细信息。- 并行团队博客上的 Stephen Toub 有另一篇博客文章 等待、UI 和死锁!哦,我的!,它详细解释了这种特殊的僵局情况。
- 我在MSDN论坛帖子中为这种僵局写了一个详尽的答案。
这个死锁足够有名,以至于它实际上已经被Microsoft演示过:
- 作者:Stephen Toub在BUILD大会上(2011年9月16日(。
- 作者:Lucian Wischik在DevConnections(2012年3月26日(。
尝试将 ConfigureAwait(false
( 与 await 操作一起使用,可能会ReadTextAsync
线程不安全,因此它会在 await 完成后挂起 UI 线程并返回到 UI 线程。