6

我正在查看 C# 中的新关键字asyncawait关键字,并试图了解它们。

我正在查看 MSDNFileStream.WriteAsync() 示例,但我不确定我是否理解某些内容。

示例如下:

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调用。

但是如果你这样做,它不等待调用完成吗?这使得它不是很异步......

4

2 回答 2

15

我怀疑问题出在您对功能的理解await上。

但是如果你这样做,它不等待调用完成吗?这使得它不是很异步......

当你await做某事时,你“异步阻塞” - 当异步操作完成时,你的异步函数将继续,但立即调用将立即完成。

因此,在您的情况下,UI线程因为返回而变得畅通Button_Click,但是当文件写入操作完成时,执行将返回(仍在UI线程中)到await表达式的末尾...然后您将关闭FileStream并完成异步函数。

如果您在表达式之后执行其他操作await(例如更新 UI),将会更清楚发生了什么。但是,是的,它确实异步的——它只允许您编写看起来是同步的代码。

于 2012-12-12T14:01:18.550 回答
2

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 立即完成,这将更有效地执行。

于 2012-12-12T14:06:10.633 回答