2012-06-01 5 views
1

내가 만들고있는 응용 프로그램은 일부 원본에서 로그를 읽고 그리드에 표시합니다. 로그는 수 MB에서 수 GB까지 될 수 있습니다. 메모리 문제를 방지하기 위해 한 번에 500 줄씩 로그를 페이징하고 있습니다. 이것이 내가하기를 원하는 것입니다 :두 스레드 간 번갈아 내기

로그를 읽고 매번 약 500 줄의 파일에 쓰는 쓰레드를 만들고 싶습니다. 그런 다음 로그가 쓰여진 다른 쓰레드에게 신호를 보냅니다. 다른 스레드는 파일을 읽고 눈금 선을 표시하고 읽은 첫 번째 스레드에 신호를 보냅니다. 파일에 쓸 로그가 더 이상 없을 때까지 계속됩니다.

이와 같이 스레드를 전환 할 수 있습니까?

답변

2

예, 물론 producer-consumer model의 변형입니다.

여기에 ThreadAutoResetEvent과 같은 몇 가지 기본 구성 블록을 사용할 수 있습니다. 은 "프로듀서는"파일 (? 어쩌면 당신이 대신 메모리 버퍼를 사용할 수 있습니다)에 로그 및 게시물을에서 라인을 읽고 다음을 읽고 다른 스레드를 신호 :

AutoResetEvent consumerEvent = new AutoResetEvent(false); 
AutoResetEvent producerEvent = new AutoResetEvent(false); 

// producer code 
while(/* lines still available */) 
{ 
    // read 500 lines 
    // write to shared file 
    consumerEvent.Set(); // signal consumer thread 
    producerEvent.WaitOne(); // wait to be signaled to continue 
} 

그리고 소비자 코드를 :

while(/* termination not received */) 
{ 
    consumerEvent.WaitOne(); // wait for the producer to finish  
    // read lines from file and put them in the grid 
    producerEvent.Set(); // allow producer to read more logs 
} 

이렇게하면 파일을 읽는 소비자와 더 많은 로그를 읽고 다음 배치를 준비하는 프로듀서간에 어느 정도의 병렬 처리가 허용됩니다.

제작자가 로그를 끝내면 파일에 특수 종료 메시지를 넣어 소비자가 정상적으로 종료되었음을 알릴 수 있습니다.

이것은 하나의 전략이며 꽤 낮은 수준이며 오류가 발생하기 쉽습니다. 공유 파일을 완전히 건너 뛸 수 있으며 BlockingCollection 형태로 메모리 내 버퍼를 사용할 수 있습니다.

텍스트의 일부 라인을 유지하기 위해 ProducerTask 클래스를 정의 :이 작업은 한 번에 500 선을 개최한다

class ProducerTask 
{ 
    public String[] Lines { get; set; } 
} 

. 다음과 같이

그런 TaskBlockingCollection (.NET 4.0 이상) 사용

BlockingCollection<ProducerTask> buffer = new BlockingCollection<ProducerTask>(1); 

// producer task 
while(/* lines still available */) 
{ 
    // read 500 lines 
    ProducerTask p = new ProducerTask(); 
    buffer.Add(p); // this will block until the consumer takes the previous task 
} 

// consumer task 
while(/* termination not received */) 
{ 
    ProducerTask p = buffer.Take(); // blocks if no task is available 
    // put the lines in the grid 
} 

훨씬 더 간단하고 우아한.

+0

감사합니다. 이것은 내가 찾고있는 것입니다. 한 번에 읽을 수있는 500 줄은 가변적이기 때문에 메모리 내 버퍼를 사용할 수 있다고 생각하지 않습니다. 어떤 숫자라도 될 수 있습니다. 게다가, 응용 프로그램이하는 다른 것들이 있기 때문에 나는 많은 양의 데이터를 메모리에 보유하고 싶지 않습니다. – Albert

0

튜더 (Tudor)의 답변에 따르면 생산자 - 소비자 패턴 구현을위한 매우 깨끗한 빌딩 ​​블록을 제공하는 TPL Dataflow을 볼 수 있습니다.