2017-09-11 4 views
1

내 응용 프로그램이 직렬로 수신 된 바이트를 처리 중이며 이상한 버그를 발견했습니다. 때로는 바이트 (항상 0x03이 됨)가 2x 처리되고 이유를 알지 못합니다.C# 동일한 직렬 수신 바이트를 두 번 처리합니다.

바이트를 받으면 += ReadExisting()을 사용하여 문자열에 추가합니다. 이 문자열은 내 버퍼를 형성합니다. 문자열이 비어있을 때까지 백그라운드 작업자가 문자열의 모든 바이트를 처리합니다. 문자열의 첫 번째 요소가 읽힌 후에 삭제되면 string.Length()은 루프 사이클 동안 매번 작은 수를 반환합니다.

private void serial_DataReceived(object sender, SerialDataReceivedEventArgs e) 
     { 
      rxBuffer += serial.ReadExisting(); // adds new bytes to buffer 

      try { backgroundWorker1.RunWorkerAsync(); } catch { } // starts background worker if it is not working already. 
     } 


     private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) 
     { 
      while (rxBuffer.Length > 0) 
      { 
       byte b = Convert.ToByte(rxBuffer[0]); // reads in the next byte  
       rxBuffer = rxBuffer.Remove(0, 1); // deletes this byte from the string 

      // ... code ... does things do the UI and stuff 

일부 직렬 바이트는 루프 2x에서 실행됩니다. 나는 내 작품에서 그것을 보았다. 몇 가지 이유로 이중 바이트는 항상 0x03입니다. rxBuffer은 프로그램의 다른 곳에서는 다루지 않습니다.

Bullseye set at (0,2) 
2:05:10 << 0x80 
2:05:10 << 0x3 
2:05:10 << 0x13 
Bullseye set at (1,2) 
2:05:10 << 0x80 
2:05:10 << 0x3 
2:05:10 << 0x3 <--- this one should not be there. 
Bullseye set at (3,0) 
2:05:10 << 0x14 
2:05:10 << 0x80 
2:05:10 << 0x3 
2:05:10 << 0x15 
Bullseye set at (3,2) 
2:05:10 << 0x80 
2:05:10 << 0x3 
2:05:10 << 0x16 
Bullseye set at (4,2) 

왜 이런 일이 발생하며 어떻게 해결할 수 있습니까? 그것은 비동기 바이트 읽기 및 백그라운드 작업자와 관련이 있습니까 ??? 빠른 & 더러운 수정에 대한

+1

2 개의 스레드에서 자원을 공유합니다. 동기화가 필요합니다. 또는 더 나은 : 스레드 안전 버퍼를 사용하십시오. – Fildor

+0

제거 작업을 수행 할 때 읽기 이벤트가 발생할 수 있습니다. 이벤트가 발생하면 인라인 코드를 방해하지 않는지 확인해야합니다. – jdweng

+0

이것이 실제로 스레드 문제인지 알아 내고 싶다면 버퍼의 현재 스레드 ID와 길이도 출력하십시오 ... – Fildor

답변

1

:

private readonly object _lock = new object(); 
private void serial_DataReceived(object sender, SerialDataReceivedEventArgs e) 
    { 
     lock(_lock) 
     { 
     rxBuffer += serial.ReadExisting(); // adds new bytes to buffer 
     } 
     try { backgroundWorker1.RunWorkerAsync(); } catch { } // starts background worker if it is not working already. 
    } 


    private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) 
    { 
     lock(_lock) 
     { 
     while (rxBuffer.Length > 0) 
     { 
      byte b = Convert.ToByte(rxBuffer[0]); // reads in the next byte  
      rxBuffer = rxBuffer.Remove(0, 1); // deletes this byte from the string 

     // ... code ... does things do the UI and stuff 
     } // end while 
     } // end lock 

더 정교한 솔루션은 클래스와 코드에 만들어진 많은 변경 사항에 대한 자세한 정보가 필요합니다.

+0

Tnx 작동하는 것 같습니다. 내 솔루션은 while 루프 함수를 호출하고 배경 작업자를 버리는 것이었다. 나는 '덜 나빠질 것'이 무엇인지 모른다. – bask185