我正在查看C#中新的async
和await
个关键字,并试图了解它们。
我正在查看MSDN FileStream.WriteAsync()
example,我不确定我是否了解某些内容。
示例如下:
using System;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.IO;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
UnicodeEncoding uniencoding = new UnicodeEncoding();
string filename = @"c:\Users\exampleuser\Documents\userinputlog.txt";
byte[] result = uniencoding.GetBytes(UserInput.Text);
using (FileStream SourceStream = File.Open(filename, FileMode.OpenOrCreate))
{
SourceStream.Seek(0, SeekOrigin.End);
await SourceStream.WriteAsync(result, 0, result.Length);
}
}
}
}
我没有得到的是await
的展示位置。您似乎无法获取Task
返回的WriteAsync()
项,因为这总是给我一个语法错误。因此,我可以将其编译为唯一的方法是将await
留给调用。
但是如果你这样做,是不是等待电话完成?这使它不是非常异步......
答案 0 :(得分:14)
我怀疑问题在于你对await
的作用有所了解。
但是如果你这样做,是不是等待电话完成?这使它不是非常异步......
当你await
某事时,你“异步阻塞” - 当异步操作完成时你的异步函数会继续,但是立即调用会立即完成。
因此,在您的情况下,UI线程将被取消阻止,因为Button_Click
返回,但是当文件写入操作完成时,执行将返回(仍在UI线程中)到await
的末尾表达式......然后你将关闭FileStream
并完成异步函数。
如果您在 await
表达式之后执行其他操作(例如更新UI),那么会更清楚。但是,它确实是异步 - 它只允许你编写看起来同步的代码。
答案 1 :(得分:1)
await在等待时实际上并没有阻止。发生的事情是编译器执行一些复杂的操作来在await之后进行所谓的所有代码的延续,并告诉任务在完成后执行该延续。
基本上,Button_Click方法的最后几行被翻译为:
FileStream SourceStream = File.Open(filename, FileMode.OpenOrCreate);
SourceStream.Seek(0, SeekOrigin.End);
Task t = SourceStream.WriteAsync(result, 0, result.Length);
t.ContinueWith(_ => SourceStream.Dispose());
当然,这是简化的,因为如果WriteAsync立即完成,这将更有效地执行。例如。