2016-02-26 45 views
0

请原谅我的无知,但我有了解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,那么它将等待完成,并且在调用该方法之后将不会运行其他代码。

+0

它是异步的,因为'await sourceStream.ReadAsync'。请注意,异步并不意味着您不会等待,这意味着如果您选择等待,则在等待时不会占用线程。 – juharr

+0

如何实际读取文件内容的全部内容?您无法调用该方法并继续执行程序 – tic

+0

*此方法“等待”响应,但消耗系统可以在此任务完成时自由地执行其他操作。 ''你不能调用这个方法并继续执行程序'' - 你当然可以,而这正是系统的功能。例如,当UI在该方法执行时继续呈现和响应。这是应用程序继续做的事情。 – David

回答

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; 
    } 
1

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

因此,这不是并行或并发编程,它只是让一个进程(代码点)等待I/O完成时允许线程处理其他请求。

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

+0

啊,这确实解释了它。我应该添加到我的问题,我应该如何有一个方法可以同时调用来读取文件的内容,并继续执行? – tic

+0

@tick - 这真是一个非常不同的东西:)我想你需要将文件长度分成开始/结束范围,为每个范围分配多个线程,并且打开一个FileStream,只读,不锁定,只读取范围,并有一些类型的最终过程,将它们全部重新组合在一起。也就是说,你可能会看到0的好处,因为你从同一个磁盘读取数据,并且O/S一次只能服务于同一个文件中的一个读取数据,所以你的瓶颈仍然是I/O。这可能不值得努力创造。 – Igor