2016-02-26 90 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