2009-04-29 20 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... 
     } 
    } 
    } 

は私がネット非同期IOストリーミング方法についていくつかのものを読んだことがある...のようなものを見て、私は2を持ついくつかの助け後にしていますこの問題に関する特定の質問。

私は、それぞれの行の全体が必要だとすれば、非同期的にこれらのファイルを読むことでパフォーマンスを向上させますが、ファイルの行間には関係がありません。 ?

第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

このコードは完璧です。私は非同期ファイルの読み込みにも同じことをします。 –

+0

私は同意します。これは甘いです。同じ問題に対して別の解決策を考案しようとしている間、私はたくさんの仕事を保存しました。 – Skurmedel

1

非同期パターンはBeginRead()/ EndRead()です。

ブーストを受けるかどうかは、読んでいるときに何が起こっているかによって大きく異なります。あなたのアプリが読書を待っている間に何かできることはありますか?そうでなければ、非同期はあまり役に立たないでしょう...

+0

はい、私はそれを読んだことがありますが、BeginRead()はバッファの長さを読み取るだけではありませんか?それはそれぞれの行を返すつもりはない、それ?または私は間違っていますか? – Ash

1

非同期読み込みでは、ブロックごとにヘッドをシークアップさせるだけです。ファイルシステム上の適切なファイルの断片化と同期読み取りを使用することで、パフォーマンスが向上します。

としては、すでにパフォーマンスがFILE_FLAG_SEQUENTIAL_SCANを参照してください私は相互運用調査推薦する超臨界である場合(特にマルチコアCPU上の)ブースト

0

を与えるべき他のスレッドにライン処理を派遣、指摘details here

パフォーマンスを向上させるかどうかを調べるために、そのフラグを持つファイルをスキャンする小さなC++アプリケーションを作成する方がいいです。

関連する問題