如何正确使用 FileStream.ReadAsync 不阻塞 UI

How to use FileStream.ReadAsync properly to not blocking UI

我是异步编程的新手。 我的 UI 中有一个按钮和文本框。我想单击该按钮,它将使用 FileStream.ReadAsync 方法读取文件,然后它应该在文本框中显示文件的结果。 问题是我不想在读取文件时阻塞我的 UI。 我认为使用 Read 方法应该这样做。但它不起作用。此方法有何不正确之处以及如何将 Read 更改为 ReadAsync?

  private  void Button_Click(object sender, RoutedEventArgs e)
        {
            string filename = @"D:\Log\log.txt";
            byte[] result;
            UnicodeEncoding uniencoding = new UnicodeEncoding();
            using (FileStream SourceStream = File.Open(filename, FileMode.Open))
            {
                result = new byte[SourceStream.Length];
                Task<int> tf = new Task<int>(()=> SourceStream.Read(result, 0, (int)SourceStream.Length));
                tf.ContinueWith((x) =>
                 {
                     try
                     {
                         string txt = Encoding.ASCII.GetString(result);
                         Dispatcher.BeginInvoke((Action)(() => txtBox.Text = txt));
                     }
                     catch (Exception ae)
                     {

                         MessageBox.Show(ae.Message);
                     }
                 });

                tf.Start();
            }

如果我的理解正确并且您只是以 ASCII 编码读取文本文件并将内容放入文本框中,那么您最好使用 File.ReadAllTextAsync(),它在 . NET 核心:

private async void Button_Click(object sender, RoutedEventArgs e)
{
    string filename = @"D:\Log\log.txt";
    try
    {
        txtBox.Text = await File.ReadAllTextAsync(filename, Encoding.ASCII);
    }
    catch (Exception ae)
    {
        MessageBox.Show(ae.Message);
    }
}

异步读取文件其实有点奇怪。有时即使你使用异步方法读取它实际上也不会异步发生。例如,FileStream constructors has a useAsync parameter, and another constructor has an options parameter where you can specify FileOptions.Asychronous. But File.Open() doesn't use either of those constructors, which means that the file access doesn't end up being asynchronous, even if you use ReadAsync(). File.ReadAllTestAsync() does.

之一

但即便如此,this issue 也讨论了 打开 文件的行为实际上并不是异步发生的,即使 reading 确实如此,如果您正在访问远程文件系统,这可能是一个问题。因此,如果您对锁定 UI 的代码有疑问,请将 await 行更改为:

txtBox.Text = await Task.Run(() => File.ReadAllTextAsync(filename, Encoding.ASCII));

这将 运行 ReadAllTextAsync 在另一个线程上。 Task.Run 是最好的方法。几乎没有理由使用 new Task().