2011-02-22 5 views
0

스레드가 이벤트를 기다리고 있는지 확인하는 방법을 궁금합니다.스레드가 이벤트를 기다리고 있는지 확인하는 방법은 무엇입니까?

public delegate void TestHandler(object sender, EventArgs eventArgs); 
class Producer 
{ 
    public event TestHandler Handler; 
    public void InvokeHandler(EventArgs eventargs) 
    { 
     var handler = Handler; 
     if (handler != null) handler(this, eventargs); 
    } 

    public Producer() 
    { 
     Task.Factory.StartNew(() => 
     { 
      while (true) 
      { 
       Thread.Sleep((new Random()).Next(0,100)); 
       InvokeHandler(new EventArgs()); 
      } }); } } 

그리고 리스너 : 하자 내가 이벤트를 제기 구성 요소를했습니다 말할

class Listener 
{ 
    private readonly BlockingCollection<EventArgs> _blockingCollection; 
    public Listener() 
    { 
     var producer = new Producer(); 
     _blockingCollection = new BlockingCollection<EventArgs>(10); 
     producer.Handler += producer_Handler; 
    } 

    void producer_Handler(object sender, EventArgs eventArgs) 
    { 
     _blockingCollection.TryAdd(eventArgs); //no error handling for simplicity sake 
    } 

    internal void ProcessEvents() 
    { 
     while (true) 
     { 
      EventArgs eventArgs; 
      try 
      { 
       if (_blockingCollection.TryTake(out eventArgs)) 
        Console.WriteLine("Received event"); 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine(ex.Message); 
      } } } } 

나는 그것을 시작한다면 : 나는 (에서 예상 된 동작있어

class Program 
    { 
     static void Main(string[] args) 
     { 
      var listner = new Listener(); 
      listner.ProcessEvents(); 
     } } 

때때로 차단 수집을 통해 이벤트가 발생합니다.

하지만 이 전화를 랩에 걸기 작업 :

Task.Factory.StartNew(() => { 
    var listner = new Listener(); 
    listner.ProcessEvents(); }); 

나는 처리 부분에 들어 가지 않을 것입니다. 그 이유는 무엇입니까? 나는 명백한 것을 놓치고 있니?

측면에서 누군가가 여기에서 도움이 될 패턴에 대한 좋은 설명을 알고 있습니까? 하나의 스레드 (주로 기본 응용 프로그램 스레드가 아님)에서 이벤트를 픽업 한 다음 개별 스레드에서 동시에 처리하여 이벤트 수가 너무 많으면 차단합니다 (일반적인 임계 값 가정)

사전에

감사합니다,

+1

작업으로 시작했을 때 처리 부분에 도달하지 못했다고 말하면 어떻게됩니까? 프로그램이 단순히 종료 되었습니까? –

+0

#paul, @stic, 내가 물어보고 싶은 것. Errormessages 및 stackdumps하시기 바랍니다. 우리는이 테스트 설정의 유물을 볼 수 있습니다. –

+0

폴, 헨크 - 운동을 몇 번 반복 할 예정이지만, 단지 (사실) 루프를 무시하고 끝내는 깨끗한 실행처럼 보입니다. – stic

답변

0

일부 로깅 메시지를 넣고 새 작업을 시작할 때 때 예외가 발생되지 않았는지 확인해야합니다 당신에게 무슨 일이 일어나고 있는지 파악하기 위해 (

Thread listenerThread = new Thread(() => 
{ 
    // print a message when the task is started 
    Console.WriteLine("Task started!"); 

    var listner = new Listener(); 
    listner.ProcessEvents(); 
}); 

// set your thread to background so it doesn't live on 
// even after you're 
listenerThread.IsBackground = true; 
listenerThread.Start(); 

Thread.join를을)는 Task.Wait()와 동일한 작업을 수행합니다. 당신은 제한 시간을 지정하지 않고 호출 할 수 있습니다, 당신은 무한한 제한 시간을 지정하거나이 테스트가 완료 될 때까지 스레드를 대기 중지하려면, 당신은 밀리 초 단위로 시간 제한을 지정합니다 중지해야하는 경우

// this will block until the thread is complete 
listenerThread.Join(Timeout.Infinite); 

을 테스트 후 비동기 인터럽트를 수행해야합니다. 인터럽트합니다 (ProcessEvents 방법에서와 같이) 당신이 잡을 거 야되는 Thread 내부 ThreadInterruptedException 제기 또한

listenerThread.Interrupt(); 

, 당신은 차단 컬렉션을 사용하고 있지만 당신의 차단 기능을 사용하지 않는 컬렉션. 나

internal void ProcessEvents() 
{ 
    while (true) 
    { 
     try 
     { 
      var myEvent = _blockingCollection.Take(); 
      Console.WriteLine("Received event"); 
     } 
     catch(ThreadInterruptedException) 
     { 
      Console.WriteLine("Thread interrupted!"); 
      break;// break out of the loop! 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.Message); 
      // Do you REALLY want to keep going if there is an unexpected exception? 
      // Consider breaking out of the loop... 
     } 
    } 
} 
+0

감사합니다. Lirik, 차단하지 않을 경우 TryTake가 감싸는 것을 인식하지 못했습니다. 뒤에있는 모니터를 기반으로 제한된 버퍼를 남기는 방법을 배우는 중 ... – stic

+0

@stic [TryTake는 비 차단] (http://msdn.microsoft.com/en-us/library/dd287184.aspx) if 절이나 다른 절에 포장하면 문제가 없습니다. [Take는 차단 중입니다.] (http://msdn.microsoft.com/en-us/library/dd287085.aspx) ... – Kiril

1

바보 : 컬렉션에 아무것도 없을 때 당신이 뭔가가있을 때까지 대신 오히려 (이 컬렉션은 할 수 있도록 설계되었습니다 것입니다) 차단하는 것, 계속 다시 시도해야 할 이유는 없다. ..

내 전화를 작업에서 랩핑 할 때 백그라운드 스레드에서 실행됩니다. 작업을 마칠 때까지 기다렸다가 종료해야합니다.

var task = Task.Factory.StartNew(/*task body*/); 
task.Wait(); 

을하고 내가 원하는 것을 가지고 기다리고 :

그 할당되고, 그 일을 가졌어요.

+0

이 작업을 수행 할 수는 있지만 여전히 'Take'차단을 사용하는 것이 좋습니다. non-blocking'TryTake'보다는 오히려 ... 뭔가를 블로킹/기다리는 소비자가있을 때, 당신은 정말로'Task' 대신에'Thread'에서 실행하기를 원할 것입니다. 차단 호출을 '중단'하는 기능). – Kiril

+0

CancellationToken을 전달하면서 새 작업을 시작합니다. try/catch를 사용하여 while 모양을 래핑하고 취소시 throw 된 예외를 처리합니다. Thread 클래스를 사용하지 않으려 고 노력하고 있는데, 얼마나 멀리 얻을 수 있는지 보겠습니다 :-) – stic

관련 문제