我正在开发一个Windows 8.1商店应用,用户可以在其中将文本保存到文件中。
我一直在努力了解如何最好地使用async并等待。
这就是我想出来的:
private async void userText_KeyDown(object sender, KeyRoutedEventArgs e)
{
if (e.Key == Windows.System.VirtualKey.Enter)
{
if (addUserImput)
{
userStringlist.Add(userBox.Text);
userBox.Text = "";
addUserImput = false;
}
await WriteToFileAsync();
addUserImput = true;
}
}
async-method看起来像这样:
private async Task WriteToFileAsync()
{
string name = "userStrings.txt";
var option = CreationCollisionOption.ReplaceExisting;
var folder = Windows.Storage.ApplicationData.Current.LocalFolder;
var file = await folder.CreateFileAsync(name, option);
await Windows.Storage.FileIO.WriteLinesAsync(file, userStringlist);
}
只要WriteToFileAsync到达await-keyword,执行就会重新开始。为了防止列表中的重复,我必须添加if语句。
这让我觉得很奇怪。我还是新手,所以我可能会错过一些东西。为什么keydown事件从顶部恢复,做了已经完成的工作?
我的“解决方法”有效,我只是不了解事件行为背后的逻辑。
答案 0 :(得分:2)
是的,这就是异步解决方案的工作原理。当你点击你的第一个实际异步操作(在这种情况下,CreateFileAsync
)时,该方法返回其调用者,该调用者返回其调用者,并最终使其完全脱离整个方法并备份到应用程序的消息循环。然后继续处理其他UI消息。其中一些消息可能是按键事件(它们最终可能在异步操作完成之前运行)。其他事件可能是绘制事件或鼠标单击事件,使您的表单可以执行与用户交互所需的任何事情。这就是防止它冻结的原因。
您要做的是防止同时运行您的代码段。如果这不是异步,那么通常使用lock
关键字来解决这个问题,但这不是异步方法的选项。您需要的是一些阻止访问代码的方法,直到该代码块的任何其他执行完成。幸运的是,是工具可用于执行此操作。您可以 使用布尔值,但这有点脆弱,并且随着应用程序复杂性的增长而容易出错。信号量是专门为此任务设计的:
private SemaphoreSlim semaphore = new SemaphoreSlim(1);
private async void Bar()
{
try
{
await semaphore.WaitAsync();
//do stuff
}
finally
{
semaphore.Release();
}
}
SemaphoreSlim
类有一个WaitAsync
方法专门设计用于异步方法,例如你的方法。您可以等到信号量空闲,执行代码,然后确保在完成时释放信号量,以便其他代码可以移动到代码块中。
答案 1 :(得分:0)
在这种情况下,您可能需要使用processed = true。检查http://msdn.microsoft.com/en-us/library/system.windows.forms.keyeventargs.handled(v=vs.110).aspx是否有效