异步读取文本文件

时间:2016-02-26 20:21:38

标签: c# asynchronous text-files

请原谅我的无知,但我在理解MSDN摘录异步读取文件内容时遇到了问题

https://msdn.microsoft.com/en-us/library/jj155757.aspx

string text = await ReadTextAsync(filePath);

...

private async Task<string> ReadTextAsync(string filePath)
{
    using (FileStream sourceStream = new FileStream(filePath,
        FileMode.Open, FileAccess.Read, FileShare.Read,
        bufferSize: 4096, useAsync: true))
    {
        StringBuilder sb = new StringBuilder();

        byte[] buffer = new byte[0x1000];
        int numRead;
        while ((numRead = await sourceStream.ReadAsync(buffer, 0, buffer.Length)) != 0)
        {
            string text = Encoding.Unicode.GetString(buffer, 0, numRead);
            sb.Append(text);
        }

        return sb.ToString();
    }
}

这种阅读是如何异步的?似乎等到ReadTextAsync完成后才返回内容。如果在该方法中插入了Thread.Sleep,那么在调用该方法之后,它将等待完成,并且不再运行任何代码。

2 个答案:

答案 0 :(得分:1)

在一个坚果shell await中确保对于I / O操作(如数据库查询,文件读取,网络写入等),在代码等待代码时线程被释放回O / S.结果在完成端口。这样你的线程或不坐在等待I / O完成,现在他们可以被O / S重用于其他活动。一旦I / O完成,O / S将重新分配新线程或使用原始线程(取决于ConfigureAwait)来恢复操作。

因此,这不是并行或并发编程,它只是允许线程在进程(代码点)等待I / O完成时为其他请求提供服务。

另请参阅Asynchronous Programming with Async and Await了解更多详情。

答案 1 :(得分:0)

问题在于我自己对async修饰符缺乏了解。 原始示例是异步运行的,但是添加到方法中的任何额外缓慢的完成代码将同步运行并等待调用线程完成。如果确实需要Sleep,则整个调用可以包装在新的Task中并调用,返回任务而不是结果。

例如,当您从外部驱动器读取时,这不会暂停程序执行。

    public Task<string> ReadTextAsync(string filePath)
    {
        var task = new Task<string>(() =>
        {
            Thread.Sleep(5000);
            using (FileStream sourceStream = new FileStream(filePath,
FileMode.Open, FileAccess.Read, FileShare.Read,
bufferSize: 4096, useAsync: true))
            {
                StringBuilder sb = new StringBuilder();

                byte[] buffer = new byte[0x1000];
                int numRead;
                while ((numRead = sourceStream.Read(buffer, 0, buffer.Length)) != 0)
                {
                    string text = Encoding.ASCII.GetString(buffer, 0, numRead);
                    sb.Append(text);
                }

                return sb.ToString();
            }
        });
        task.Start();
        return task;
    }