2

우리는 ConcurrentQueue를 사용하여 3 개의 스레드간에 데이터를 공유합니다. 스레드 A는 지속적으로 대기열을 데이터로 채 웁니다. 스레드 B는이 데이터를 파일에 기록하도록 설계되었습니다. 스레드 C는 대기열에서 가장 어린 항목을 검색하거나 (가능한 한 가장 가깝게), 일부 작업을 수행하고 결과를 화면에 표시합니다.대기열에서 작동하는 다중 스레드가있는 ConcurrentQueue의 최하위 요소에 액세스

스레드 B는 시간에 파일 쓰기 작업을 클러스터하기 위해이 같은 일을 수행합니다

if (cq.Count > 100) 
{ 
    while (cq.Count > 1) 
    { 
     qElement = PopFromCq(cq); // PopFromCq uses cq.TryDequeue() 
     bw.Write(qElement.data); // bw is a binary writer 
    } 
} 
else 
{ 
    System.Threading.Thread.Sleep(10); 
} 

즉, 그 다음, 대기열 적어도 100 개 요소를 기다립니다 디스크에 기록합니다. 항상 큐에 적어도 하나의 항목을 유지하지만 스레드 C가 항상 적어도 하나의 항목에 액세스 할 수 있기를 원하는 이유가 있습니다. 이 루프에서

while (threadsRunning) 
{ 
    System.Threading.Thread.Sleep(500); // Update twice per second 
    ProcessDataAndUpdateScreen(cq.ElementAt(cq.Count - 1)); // our terrible attempt at looking at the latest (or close to latest) entry in the queue 
} 

, 우리가 때때로 인해 디스크에 데이터를 기록하는 스레드 사이의 경쟁, 그리고 cq.ElementAt (CQ에 예외가 :

스레드 C의 루프처럼 보인다. Count-1) 호출. ,

  1. cq.Count가로 계산되는 시간으로
  2. (90)는, 스레드 B가 이미 루프를 시작 말하고 그것을 쓸 수있는 큐에서 데이터를 dequeueing있다 : 나는 다음과 같이 어떤 일이 일어나고이다 생각 디스크
  3. cq.ElementAt()가 호출 될 때까지는 스레드 B가 (cq.Count - 1)이 더 이상 큐의 유효한 항목을 가리키는 것과 같은 항목을 소비했습니다.

대기열에서 작동중인 다중 스레드가있는 상태에서 가장 최근의 항목에 액세스하는 좋은 방법에 대한 아이디어가 있습니까?

감사

+0

작동하는지 (따라서 코멘트에 쓰는 지) 확실하지 않지만 'LastOrDefault()'가 문제를 피하는 데 도움이 될 수 있습니까? http://msdn.microsoft.com/en-us/library/bb301849.aspx를 참조하십시오. –

답변

2

는 A-B의 통신 큐 통과 모두 A-C의 통신에 필요한 그인가? 스레드 A가 대기열에 각 항목을 쓰고 (B가 읽고 로그하도록), 항목을 휘발성 속성에 어딘가에 저장하면 어떨까요? 가장 어린 요소를 얻고 싶을 때마다 C는 그 속성에서 직접 읽을 수 있습니다.

편집 : 휘발성 속성에만 의존하는 대신 "가장 젊은 항목"속성을 설정하고 읽으려면 실제로는 Interlocked.CompareExchange<T>(T, T)을 사용해야합니다.

+0

64 비트 레퍼런스에서 '휘발성'작동합니까? 어쨌든 Interlocked op가 더 좋을 것입니다. –

+0

당신 말이 맞아 ... 인터록 .compareExchange (Object, Object)가 트릭을 할 것입니다. – Eric

+0

나는 Thread B의 TryDequeue와 Thread C의 .ElementAt를 lock()으로 보호했다. Interlocked.CompareExchange() 함수를 사용하는 방법을 잘 모르겠습니다. 그게 내 개체에 필드를 추가하고 새 항목이 대기열에 추가 될 때마다, 대기열에서 가장 어린 항목에 대한 필드의 설정을 해제하고 들어오는 항목에 대해 설정해야합니까? – SomethingBetter