2009-04-29 62 views
4

我有一個應用程序需要遍歷文本文件中的所有行,超過千兆字節的大小。其中一些文件有10或100幾百萬行。如何在C#2.0中執行異步文件讀取?

我目前(和同步)閱讀的例子,看起來像......

using (FileStream stream = new FileStream(args[0], FileMode.Open, FileAccess.Read, FileShare.Read)) { 
    using (StreamReader streamReader = new StreamReader(stream)) { 
     string line; 
     while (!string.IsNullOrEmpty(line = streamReader.ReadLine())) {   
     //do stuff with the line string... 
     } 
    } 
    } 

我看了一些東西有關.NET異步IO流的方法,而我一些幫助,2後關於這個問題的具體問題。

首先,如果我需要每行的總數,這些文件非常短,但長度各不相同,我會通過異步讀取這些文件來獲得性能提升(文件中每行之間沒有關係) ?

二,如何將上述代碼轉換爲異步讀取,以便我可以像現在一樣逐行處理每一行?

回答

7

而不是使行讀取異步,您可能會嘗試使該文件讀取異步。這包含了單個工作人員委託中的問題中的所有代碼。

static void Main(string[] args) 
    { 
     WorkerDelegate worker = new WorkerDelegate(Worker); 
     // Used for thread and result management. 
     List<IAsyncResult> results = new List<IAsyncResult>(); 
     List<WaitHandle> waitHandles = new List<WaitHandle>(); 

     foreach (string file in Directory.GetFiles(args[0], "*.txt")) 
     { 
      // Start a new thread. 
      IAsyncResult res = worker.BeginInvoke(file, null, null); 
      // Store the IAsyncResult for that thread. 
      results.Add(res); 
      // Store the wait handle. 
      waitHandles.Add(res.AsyncWaitHandle); 
     } 

     // Wait for all the threads to complete. 
     WaitHandle.WaitAll(waitHandles.ToArray(), -1, false); // for < .Net 2.0 SP1 Compatibility 

     // Gather all the results. 
     foreach (IAsyncResult res in results) 
     { 
      try 
      { 
       worker.EndInvoke(res); 
       // object result = worker.EndInvoke(res); // For a worker with a result. 
      } 
      catch (Exception ex) 
      { 
       // Something happened in the thread. 
      } 
     } 
    } 

    delegate void WorkerDelegate(string fileName); 
    static void Worker(string fileName) 
    { 
     // Your code. 
     using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) 
     { 
      using (StreamReader streamReader = new StreamReader(stream)) 
      { 
       string line; 
       while (!string.IsNullOrEmpty(line = streamReader.ReadLine())) 
       { 
        //do stuff with the line string... 
       } 
      } 
     } 
    } 
+0

此代碼非常完美。我會爲異步文件讀取做同樣的事情。 – 2009-04-29 09:51:25

1

異步模式是BeginRead()/ EndRead()。

你是否得到提升很大程度上取決於你在做什麼讀取時發生了什麼。在等待讀取時,您的應用程序可以執行其他操作嗎?如果沒有,那麼異步將不會有太大的幫助...

+0

是的我已經讀過,但沒有BeginRead()onlye讀取緩衝區的字節長度?這不會返回每一行是嗎?還是我誤會了? – Ash 2009-04-29 02:12:49

1

異步讀取最終會讓磁頭爲每個塊尋找更多。通過對文件系統上的文件進行良好的碎片整理並使用同步讀取,您將獲得更好的性能提升。

前面已經指出的那樣,調度行處理其他線程應該給升壓(特別是多核心CPU)

0

如果性能是超臨界我會建議互操作研究爲FILE_FLAG_SEQUENTIAL_SCANdetails here

最好還是編寫一個小型的C++應用程序,通過掃描文件並打開該標記來查看它是否可以提高性能。