2012-04-08 3 views
0

앱을 닫을 때 앱이 여전히 작동하는 이유.
직렬 포트에서 데이터를 읽음으로써 발생하는 것 같습니다.

ComboBox에서 직렬 포트 번호를 선택합니다.
기능 직렬 포트의 데이터에 따라 WriteData 업데이트 확인란을 선택합니다.앱이 종료되지 않습니다.

// Choosing of communication port from ComboBox 
    private void comboBoxCommunication_SelectionChanged(object sender, SelectionChangedEventArgs e) 
    { 
     if (serialPort.IsOpen) 
     { 
      serialPort.DataReceived -= new System.IO.Ports.SerialDataReceivedEventHandler(Recieve); 
      serialPort.Close(); 
     } 
     try 
     { 
      ComboBoxItem cbi = (ComboBoxItem)comboBoxKomunikacia.SelectedItem; 
      portCommunication = cbi.Content.ToString(); 
      serialPort.PortName = portCommunication; 
      serialPort.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(Recieve); 
      serialPort.BaudRate = 2400; 
      serialPort.Open(); 
      serialPort.DiscardInBuffer(); 
     } 
     catch (IOException ex) 
     { 
      MessageBox.Show(ex.ToString(), "Error!", MessageBoxButton.OK, MessageBoxImage.Error); 
     } 
    } 

    // Close the window 
    private void Window_Closed(object sender, EventArgs e) 
    { 
     if (serialPort.IsOpen) 
     {     
      serialPort.DataReceived -= new System.IO.Ports.SerialDataReceivedEventHandler(Recieve);     
      serialPort.Close(); 
     } 
    } 

    // Data reading 
    private delegate void UpdateUiTextDelegate(char text); 
    private void Recieve(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) 
    { 
     if (serialPort.IsOpen) 
     { 
      try 
      { 
       serialPort.DiscardInBuffer(); 
       char c = (char)serialPort.ReadChar(); 
       Dispatcher.Invoke(DispatcherPriority.Send, 
        new UpdateUiTextDelegate(WriteData), c);      
      } 
      catch(IOException ex) 
      { 
       MessageBox.Show(ex.ToString(), "Error!", MessageBoxButton.OK, MessageBoxImage.Error); 
      } 
     } 
    } 

    // Update of checkboxes 
    private void WriteData(char c) { ... } 
+0

다른 스레드가 있습니까? Closed 이벤트가 예상대로 실행되고 있는지 (디버거/로거) 확인할 수 있습니까? –

+1

'serialPort' 객체가 처분 가능하다면 (그리고'SerialPort'가 있다고 생각합니다),이 코드에서 제대로 처분하지 않을 가능성이 있습니다. 변수의 범위가보다 잘 제어되고'using' 블록에 래핑 될 수 있도록 변수를 다시 구조화 할 수 있습니다. – David

+0

@Henk Holterman - 다른 스레드 없음. 앱이 정상적으로 닫힙니다. 직렬 포트에서 데이터를 읽기 시작할 때만 제대로 닫히지 않습니다. –

답변

3

귀하의 코드가 close()를 호출하여 프로그램을 차단, 교착 상태가 발생할 가능성이 높다 :
여기 추출물입니다. 문제 문은 Dispatcher.Invoke() 호출입니다. 이 호출은 UI 스레드가 호출을 전달할 때까지 완료 할 수 없습니다. 교착 상태는 Close()를 호출하고 동시에 DataReceived 이벤트가 실행 중일 때 발생합니다. 이벤트가 실행 중이기 때문에 Close() 호출을 완료 할 수 없습니다. UI 스레드가 유휴 상태가 아니기 때문에 Invoke()를 완료 할 수 없기 때문에 이벤트 핸들러를 완료 할 수 없습니다. Close() 호출에서 멈 춥니 다. 교착 상태 도시.

이것은 버그가있어서 코드에서 발생할 가능성이있는 특히입니다. DataReceived에서 DiscardInBuffer()를 호출합니다. 이렇게하면 수신 된 데이터가 버려져 다음 ReadChar() 호출이 잠시 차단되어 더 많은 데이터가 수신 될 때까지 기다리고, 더 이상 아무것도 보내지 않으면 영원히 기다릴 수 있습니다.

DiscardInBuffer() 호출을 삭제하고 대신 Dispatcher.BeginInvoke()를 사용하여이 문제를 해결하십시오.

관련 문제