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) { ... }
4

1 回答 1

3

您的代码很可能会导致死锁,从而在 Close() 调用上阻塞您的程序。问题陈述是 Dispatcher.Invoke() 调用。在 UI 线程调度调用之前,该调用无法完成。当您调用 Close() 并且 DataReceived 事件正忙于执行时,就会发生死锁。Close() 调用无法完成,因为事件正在运行。事件处理程序无法完成,因为 Invoke() 无法完成,因为 UI 线程没有空闲,它卡在 Close() 调用中。死锁城。

尤其可能发生在您的代码中,因为它有一个错误。您在 DataReceived 中调用 DiscardInBuffer()。这会丢弃接收到的数据,因此下一次 ReadChar() 调用将阻塞一段时间,等待接收更多数据,如果设备不再发送任何内容,可能会永远阻塞。

通过删除 DiscardInBuffer() 调用并改用 Dispatcher.BeginInvoke() 来解决此问题。

于 2012-04-08T13:23:18.340 回答