使用C#5.0异步读取文件

本文关键字:读取 文件 异步 C#5 使用 | 更新日期: 2023-09-27 17:58:50

我刚开始使用C#的新async功能。我已经阅读了很多关于并行下载等的操作方法,但没有阅读/处理文本文件。

我有一个用来过滤日志文件的旧脚本,我想我可以尝试升级它。但是我不确定我对新async/await语法的使用是否正确。

在我的脑海中,我看到了逐行读取文件,并将其传递给不同的线程进行处理,这样它就可以在不等待结果的情况下继续。

我的想法是否正确,或者实现这一点的最佳方式是什么?

static async Task<string[]> FilterLogFile(string fileLocation)
{
    string line;
    List<string> matches = new List<string>();
    using(TextReader file = File.OpenText(fileLocation))
    {        
        while((line = await file.ReadLineAsync()) != null)
        {
            CheckForMatch(line, matches);
        }
    }
    return matches.ToArray();
}

完整的脚本:http://share.linqpad.net/29kgbe.linq

使用C#5.0异步读取文件

在我的脑海中,我看到了逐行读取文件,并将其传递给不同的线程进行处理,这样它就可以在不等待结果的情况下继续。

但这不是您的代码所做的。相反,当所有读取完成时,您将(异步)返回一个数组。如果您真的想逐个异步返回匹配项,则需要某种异步集合。您可以使用TPL数据流中的一个块来实现这一点。例如:

ISourceBlock<string> FilterLogFile(string fileLocation)
{
    var block = new BufferBlock<string>();
    Task.Run(async () =>
    {
        string line;
        using(TextReader file = File.OpenText(fileLocation))
        {        
            while((line = await file.ReadLineAsync()) != null)
            {
                var match = GetMatch(line);
                if (match != null)
                    block.Post(match);
            }
        }
        block.Complete();
    });
    return block;
}

(您需要添加错误处理,可能是通过错误处理返回的块。)

然后将返回的块链接到另一个将处理结果的块。或者您可以直接从块中读取它们(通过使用ReceiveAsync())。


但从完整的代码来看,我不确定这种方法是否对您有用。由于您处理结果的方式(分组,然后按每组中的计数排序),在获得所有结果之前,您无法对它们做太多处理。