2010-07-13 2 views
3

단일 스레드 루프를 사용하는 경우 스레드를 수면 상태로 두어 초당 보내는 메시지를 쉽게 제한 할 수있었습니다 (예 : Thread.Sleep(1000/MessagesPerSecond)).하지만 이제는 병렬 스레드는 더 이상 올바르게 작동하지 않습니다.Parallel.For 사용시 조절

누구나 병렬 스레드를 사용할 때 보내는 메시지를 조절하는 방법에 대한 제안이 있습니까?

Parallel.For(0, NumberOfMessages, delegate(int i) { 

    // Code here 

    if (MessagesPerSecond != 0) 
     Thread.Sleep(1000/MessagesPerSecond); 
}); 

답변

4

AutoResetEvent와 타이머를 사용하십시오. 타이머가 작동 할 때마다 Set AutoResetEvent를 사용하십시오.

그런 다음 메시지를 전송하기 전에 AutoResetEvent에 WaitOne 메시지를 보내는 프로세스를 갖도록하십시오.

private static readonly AutoResetEvent _Next = new AutoResetEvent(true); 
    private static Timer _NextTimer; 

    private static void SendMessages(IEnumerable<Message> messages) 
    { 
     if (_NextTimer == null) 
      InitializeTimer(); 

     Parallel.ForEach(
      messages, 
      m => 
      { 
       _Next.WaitOne(); 
       // Do something 
      } 
      ); 
    } 

    private static void SetNext(object state) 
    { 
     _Next.Set(); 
    } 
2

당신은 당신의 병렬 루프가 준비 메시지로 채우는 것이다 공유 ConcurrentQueue를 사용하는 것이 좋습니다. System.Threading.Timer을 사용하여 원하는 간격으로 대기열에서 메시지를 가져 와서 보냅니다. 이 디자인은 전송할 메시지를 작성하는 것이 비용이 많이 드는 경우에만 의미가 있습니다. 메시지의 실제 전송이 값 비싼 부분이라면 루프를 병렬로 실행할 이유가 없습니다.

메시지를 보낸 후에 타이머를 중지해야하는 경우 몇 가지 추가 작업을 수행해야하지만이 디자인은 비동기 메시지 대기열을 처리해야하는 제한된 메시지 보낸 사람에게 적합합니다. 고려해야 할 또 다른 경계는 메시지가 처리 될 수있는 것보다 빠르게 대기하는 '메시지 더미 (message pile-up)'입니다. 이 경우 버그를 나타낼 수 있으므로 오류가 발생하거나 BlockingCollection을 사용하는 것이 좋습니다.