FileStream WriteAsync并等待混淆

时间:2012-12-12 13:56:52

标签: c# .net filestream async-await

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

我正在查看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留给调用。

但是如果你这样做,是不是等待电话完成?这使它不是非常异步......

2 个答案:

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