2011-08-18 2 views
0

저는 C#에서 멀티 스레드 프로젝트를 진행하고 있습니다. 작업자 스레드를 제어하기위한 아이디어는 기대만큼 쉽게 작동하지 않습니다.C#의 스레드 동기화 (모니터 대기/펄스 사용)

메인 GUI 윈도우가 시작될 때 스레드가 생성되고, 여기가 실행되는 기능입니다 : 버튼이 GUI를 클릭하면

private void continueReading() 
    { 
     while (true) 
     { 
      lock (_lock) 
      { 
       while (!startDAQ) 
        Monitor.Wait(_lock); 
       startDAQ = false; 
       logging = true; 

       daqTaskComponent1.ReadAsync(); 
      } 
     } 

    } 

는 지금, startDAQ true로 설정하고, _lock한다 ReadAsync()를 호출하는 스레드를 시작하기 위해 펄스가 울립니다.

Async의 콜백 함수에서 동일한 _lock 객체를 잠그고 계산을 수행 한 다음 startDAQ를 true로 설정하고 다시 펄스합니다.

이렇게하면 콜백이 더 많은 데이터를 처리 할 준비가되었을 때만 Async 기능을 호출 할 수 있습니다.

문제는 continueReading 스레드가 Monitor.Wait에서 일시 중지되도록하고 일시 중지하기 전에 ReadAsync가 호출 된 경우 콜백을 허용함으로써 데이터 수집을 안전하게 일시 중지 할 수 있어야합니다. 이 제대로 작동되지 않고

lock (_lock) 
    { 
     startDAQ = false; 
     Monitor.PulseAll(_lock); 
     while (logging) 
      Monitor.Wait(_lock); 
    } 

좀 교착 상태를 받고 있어요 :

은 사용자가 데이터 수집을 일시 중지 버튼을 다시 클릭 할 때 내가 실행 해요 코드입니다. 이것은 모니터와 대기/펄스를 사용하여 스레드간에 신호를 보내는 첫 번째 시간이기 때문에 약간 어려움을 겪었으며이를 처리하는 더 쉬운 방법이 있다는 느낌이 들었습니다. 어떤 도움이나 제안을 주시면 감사하겠습니다.

편집 : 다음은 콜백 함수에서 관련 코드 :

lock (_lock) 
    { 
     //Lots of code here that just manipulates the data passed to the callback 
     startDAQ = true; 
     logging = false; 
     Monitor.PulseAll(_lock); 
    } 

추가 내가 원래 내 코드를 붙여 넣을 때 깜빡 로깅 부울.

+0

문제가 무엇인지 설명하십시오. 적절하게 잘못된 해결 방법을 얻으려고하면 엉망이 될 수 있습니다. – PVitt

+0

문제는 현재 코드에서 교착 상태가 발생한다는 것입니다. 루프를 실행하는 스레드가 어떻게 안전하게 멈출 수 있는지 잘 모르겠습니다. 사용자가 버튼을 클릭하여 ReadAsync를 호출하는 스레드를 시작하고 중지 할 수있게하려고합니다. 사용자가 스레드를 중지하면 콜백 함수에 문제를 일으킬 일부 정리를 수행해야하는데, 이는 정리 대기가 발생하기 전에 보류중인 ReadAsync가 완료되어야하는 이유입니다. – Shaun

+0

startDAQ는 * volatile *로 선언해야합니다. –

답변

0

(아직 비동기이므로) ReadAsync을 GUI 스레드에서 호출하면 완료 콜백에서 다시 호출하는 것이 좋습니다. 다른 (명시적인) 스레드 또는 동기화가 필요 없습니다.

+0

나는 어떤 컨텍스트 콜백이 수행되고 있는지 전혀 알지 못했다. 새 스레드에 있습니까? 사용자가 데이터 수집을 일시 중지 할 수 있도록 호출 프로세스가 시작되면 호출 프로세스를 중단하는 방법을 알지 못합니다. – Shaun

+0

콜백은 스레드 풀 스레드의 컨텍스트에있게됩니다. 인터럽트하려면 완료 콜백에 'ReadAsync'를 다시 호출하지 않도록 신호를 보냅니다. 나는 이것을'ManualResetEvent'로 추천 할 것입니다. 콜백에서 시간 초과가 0 인 이벤트를 기다리십시오. 대기가 실패하면 다시 'ReadAsync'를 호출하지 마십시오. –

+0

나는 당신의 제안을 시도하고 시작할 때 잘 동작하지만, 여전히 멈추는 문제가있다.비동기 콜백이 완료되고 일부 null 참조 오류가 발생하기 전에 내 버튼의 이벤트 핸들러가 객체를 완료하고 정리합니다. 콜백이 완료 될 때만 설정되는 다른 이벤트를 설정하려고 시도했지만 콜백을 기다리는 이벤트 핸들러를 설정하면 교착 상태가 발생하기 때문에 동일한 스레드에서 이벤트 핸들러와 콜백이 실행되고있는 것 같습니다. – Shaun