2009-04-29 7 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를 몇 가지 도움이 후입니다 이 문제와 관련된 특정 질문.

첫째로, 나는 ussually 짧은 각 줄의 전체가 필요하지만 비동기 적으로 이러한 파일을 읽음으로써 성능 향상을 얻을 수 있지만 길이가 다양합니다 (파일의 각 줄 사이에는 아무 관계도 없습니다) ?

둘째, 위의 코드를 비동기 읽기로 변환하려면 어떻게해야합니까? 지금은 각 행을 하나씩 처리 할 수 ​​있습니까?

답변

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++ 응용 프로그램을 작성하는 것이 좋습니다.

관련 문제