c# - 如何异步 Files.ReadAllLines 并等待结果?

标签 c# .net asynchronous async-await c#-5.0

我有以下代码,

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        button1.IsEnabled = false;

        var s = File.ReadAllLines("Words.txt").ToList(); // my WPF app hangs here
        // do something with s

        button1.IsEnabled = true;
    }

Words.txt 有很多我读入 s 变量的单词,我正在尝试使用 asyncawait C# 5 中使用 Async CTP Library 的关键字,因此 WPF 应用程序不会挂起。到目前为止,我有以下代码,

    private async void button1_Click(object sender, RoutedEventArgs e)
    {
        button1.IsEnabled = false;

        Task<string[]> ws = Task.Factory.FromAsync<string[]>(
            // What do i have here? there are so many overloads
            ); // is this the right way to do?

        var s = await File.ReadAllLines("Words.txt").ToList();  // what more do i do here apart from having the await keyword?
        // do something with s

        button1.IsEnabled = true;
    }

目标是以异步方式而不是同步方式读取文件,以避免 WPF 应用卡住。

感谢任何帮助,谢谢!

最佳答案

更新: File.ReadAll[Lines|Bytes|Text] 的异步版本, File.AppendAll[Lines|Text]File.WriteAll[Lines|Bytes|Text]现在已经merged into .NET Core并随 .NET Core 2.0 一起提供。它们也包含在 .NET Standard 2.1 中。

使用 Task.Run ,它本质上是 Task.Factory.StartNew 的包装器,用于异步包装器 is a code smell .

如果您不想使用阻塞函数浪费 CPU 线程,您应该等待一个真正的异步 IO 方法, StreamReader.ReadToEndAsync ,像这样:

using (var reader = File.OpenText("Words.txt"))
{
    var fileText = await reader.ReadToEndAsync();
    // Do something with fileText...
}

这将得到整个文件作为 string而不是 List<string> .如果您需要换行,则可以在之后轻松拆分字符串,如下所示:

using (var reader = File.OpenText("Words.txt"))
{
    var fileText = await reader.ReadToEndAsync();
    return fileText.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
}

编辑:这里有一些方法可以实现与File.ReadAllLines相同的代码。 ,但以真正异步的方式。代码基于 File.ReadAllLines 的实现本身:

using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;

public static class FileEx
{
    /// <summary>
    /// This is the same default buffer size as
    /// <see cref="StreamReader"/> and <see cref="FileStream"/>.
    /// </summary>
    private const int DefaultBufferSize = 4096;

    /// <summary>
    /// Indicates that
    /// 1. The file is to be used for asynchronous reading.
    /// 2. The file is to be accessed sequentially from beginning to end.
    /// </summary>
    private const FileOptions DefaultOptions = FileOptions.Asynchronous | FileOptions.SequentialScan;

    public static Task<string[]> ReadAllLinesAsync(string path)
    {
        return ReadAllLinesAsync(path, Encoding.UTF8);
    }

    public static async Task<string[]> ReadAllLinesAsync(string path, Encoding encoding)
    {
        var lines = new List<string>();

        // Open the FileStream with the same FileMode, FileAccess
        // and FileShare as a call to File.OpenText would've done.
        using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, DefaultBufferSize, DefaultOptions))
        using (var reader = new StreamReader(stream, encoding))
        {
            string line;
            while ((line = await reader.ReadLineAsync()) != null)
            {
                lines.Add(line);
            }
        }

        return lines.ToArray();
    }
}

关于c# - 如何异步 Files.ReadAllLines 并等待结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13167934/

相关文章:

c# - 在 C# 中使用 Web API 和 MS Graph SDK 访问 Microsoft Graph 时出现问题

c# - 异步任务和锁

.net - 什么是队列长度峰值

c# - C# 设置中的接口(interface)

iOS - 同时运行多个异步请求

javascript - 异步获取数据,将结果聚合到一个对象。默认情况下,对象是否被 javascript 锁定?

c# - 使用 RedGate Memory Profiler 了解 ASP.net 中的内存泄漏

c# - 帮我找到一个适用于 asp.net 应用程序的最小摩擦日志记录解决方案

c# - 在没有第 3 方库的情况下在 .NET 中刻录(视频)DVD

javascript - 获取数据时如何迭代不同的URL?