2014-01-07 2 views
2

직렬 포트에서 데이터를 수신 할 때마다 호출되는 이벤트 처리기가 있습니다.이 이벤트를 호출하면 모든 데이터가 처리 될 때까지 데이터의 개별 바이트를 처리합니다.직렬 포트에서 데이터를 처리하는 동안 직렬 포트 스레드 잠금

제 질문은이 IBSerialPort_DataReceived 이벤트 처리기가 비동기 적으로 다시 호출되지 않도록하려면 어떻게해야합니까? 즉, ProcessByte 메서드가 처음부터 호출되었을 때 바이트를 처리하고있는 중입니다. 한 번에 하나의 스레드에서 실행됩니다.

void IBSerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) 
{ 
    while (BytesToRead > 0) 
    { 
    ProcessByte((byte)ReadByte()); 
    } 
} 
+2

잠금 장치를 사용할 수 있습니까? – i3arnon

+0

포럼 사이트와 달리 "감사"또는 "도움을 주신 분께"또는 서명을 사용하지 않습니다. "[안녕하세요, '고마워,'태그 라인 및 인사말을 게시물에서 삭제해야합니까? '(http://meta.stackexchange.com/questions/2950/should-hi-thanks-taglines-and-salutations-be)를 참조하십시오. -removed-from-posts) –

답변

2

먼저 사용중인 라이브러리에 문서를 읽어 - 이벤트는 비동기 적으로 제기 될 수 있는가? 그렇지 않다면 당신은 끝났습니다.

업데이트 : 분명히이 특별한 사건은 동시에 제기 될 수 없습니다. 한스 패전트의 대답을보십시오. 같은 인스턴스에서 잠글 경우이를 잡으면 다른 곳에 당신이 죽은 잠금을 얻거나 할 수 있습니다, 당신은 잠금을 사용하고 있는지 지금

object myLock = new object(); 
void IBSerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) 
{ 
    lock(myLock) 
    { 
     while (BytesToRead > 0) 
     { 
      ProcessByte((byte)ReadByte()); 
     } 
    } 
} 

관리법 :

은 수 있다면, 하나의 전략은 lock을 사용하는 것입니다 잠시 동안 동일한 잠금 장치를 사용하면 처리를 보류하게됩니다.

다음 : 일반적으로 설명서는 이벤트가 동시에 발생하여 재진입을 처리해야하는지 여부를 알려줍니다 (예 : System.Threading.Timer의 Tick 이벤트입니다.하지만 항상 그런 것은 아닙니다. 예 : WinRT 설명서가없는 serverly DatagramSocketMessageReceived 이벤트.

+1

이것은 필요하지 않습니다. –

+0

저는 첫 번째 문장을 돋보이게하고 업데이트를 포함 시켰습니다. – markmnl

4

이것은 SerialPort 클래스 내부에서 이미 연동되어 있습니다. 이벤트 처리기가 실행중인 경우 DataReceived 이벤트가 다시 실행되지 않도록하는 내부 잠금이 있습니다.

당신은 내가 여기를 재현하는 것은 Reference Source에 관련 코드를 볼 수 있습니다

private void CatchReceivedEvents(object src, SerialDataReceivedEventArgs e) 
    { 
     SerialDataReceivedEventHandler eventHandler = DataReceived; 
     SerialStream stream = internalSerialStream; 

     if ((eventHandler != null) && (stream != null)){ 
      lock (stream) { 
       // SerialStream might be closed between the time the event runner 
       // pumped this event and the time the threadpool thread end up 
       // invoking this event handler. The above lock and IsOpen check 
       // ensures that we raise the event only when the port is open 

       bool raiseEvent = false; 
       try { 
        raiseEvent = stream.IsOpen && (SerialData.Eof == e.EventType || BytesToRead >= receivedBytesThreshold); 
       } 
       catch { 
        // Ignore and continue. SerialPort might have been closed already! 
       } 
       finally { 
        if (raiseEvent) 
         eventHandler(this, e); // here, do your reading, etc. 
       } 
      } 
     } 
    } 

참고이 코드에서 lock (stream) 문. 또한 DataReceived 이벤트 핸들러는 무언가가 수신되지 않으면 호출되지 않는다는 것을 알 수 있습니다. 그리고 SerialData.Eof 이벤트 유형을주의해야합니다.이 이벤트 유형은 상당한 수의 프로그래머를 트집했습니다.

도움이 필요하지 않습니다.