2013-02-11 124 views
9

我剛剛開始使用C#的新async功能。我已經閱讀了大量關於並行下載等的操作方法,但是讀取/處理文本文件時沒有任何操作。使用C#5.0異步讀取文件

我有一箇舊腳本,我用它來過濾日誌文件,並認爲我會去升級它。但是,我不確定我的新語法的使用是否正確。

在我的腦海裏,我看到這樣逐行閱讀文件,並將它傳遞給不同線程進行處理,因此它可以繼續而不用等待結果。

我是否正確地思考它,或者實現它的最佳方式是什麼?

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

+0

剛看過[msdn文檔](http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx),它清楚地表明我正在考慮錯誤中的關鍵字辦法。在這種情況下,我認爲他們可以做很多事情來提高績效。 – 2013-02-11 14:16:22

+1

我可以推薦這個嗎? http://blog.jerrynixon.com/2012/06/windows-8-how-to-read-files-in-winrt.html – 2013-02-11 15:24:42

回答

9

在我腦子裏,我看到這行讀取文件行並通過它進行處理不同的線程,因此它可以繼續,而不等待結果。

但是,這不是你的代碼。相反,當所有讀取完成後,您將(異步)返回一個數組。如果你真的想一個接一個地異步返回匹配,你需要某種異步集合。你可以使用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())。


但看着完整的代碼,我不確定這種方法對您有用。由於你處理結果的方式(分組,然後按每個組的數量進行排序),除非你擁有所有結果,否則你不能對它們做很多事情。

+0

這樣做更有意義。感謝示例tpl數據流代碼。我是否應該等待比賽列表或「CheckForMatch」方法?因爲它是我想象它與同步運行沒有太大區別。 – 2013-02-11 13:55:43

+1

@Sam你應該只在有意義的地方使用'await',這主要是在使用IO的代碼中。與同步代碼的區別在於:1. await file.ReadFileAsync()不會阻塞線程,所以效率更高。 2.您可以在讀取結果時處理結果,而不會阻塞另一個線程。 – svick 2013-02-11 15:13:26