C# Winform freezing on SerialPort.Close(C# Winform 在 SerialPort.Close 上冻结)
问题描述
我有一个在 SerialPort 上执行异步 IO 的 winform 程序.但是,我会定期遇到程序在 SerialPort.Close() 调用上冻结的问题,似乎是随机的.
I have a winform program that does some asynchronous IO on a SerialPort.  However, I'm periodically running into an issue with the program freezing on the SerialPort.Close() call, seemingly at random.
我认为这是一个线程安全问题,但如果是,我不确定如何解决.我尝试使用端口打开/关闭功能添加/删除异步 DataReceived 处理程序并丢弃端口上的输入和输出缓冲区,但它似乎没有做任何事情.我认为重要的 SerialPort 代码如下:
I think it's a thread safety issue, but I'm not sure how to fix it if it is.  I tried adding/removing the async DataReceived handler with the port open/close functions and discarding the in and out buffers on the port, but it doesn't seem to do anything.  I think the important SerialPort code is below:
using System;
using System.Collections.Generic;
using System.IO.Ports;
public class SerialComm
{
  private object locker = new object();
  private SerialPort port;
  private List<byte> receivedBytes;
  public SerialComm(string portName)
  {
    port = new SerialPort(portName);
    port.BaudRate = 57600;
    port.Parity = Parity.None;
    port.DataBits = 8;
    port.StopBits = StopBits.One;
    receivedBytes = new List<byte>();
  }
  public void OpenPort()
  {
    if(port!=null && !port.IsOpen){
      lock(locker){
        receivedBytes.Clear();
      }
      port.DataReceived += port_DataReceived;
      port.Open();
    }
  }
  public void ClosePort()
  {
    if(port!=null && port.IsOpen){
      port.DataReceived -= port_DataReceived;
      while(!(port.BytesToRead==0 && port.BytesToWrite==0)){
        port.DiscardInBuffer();
        port.DiscardOutBuffer();
      }
      port.Close();
    }
  }
  private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
  {
    try{
      byte[] buffer = new byte[port.BytesToRead];
      int rcvdBytes = port.Read(buffer, 0, buffer.Length);
      lock(locker){
        receivedBytes.AddRange(buffer);
      }
      //Do the more interesting handling of the receivedBytes list here.
    } catch (Exception ex) {
      System.Diagnostics.Debug.WriteLine(ex.ToString());
      //put other, more interesting error handling here.
    }
  }
}
更新
感谢@Afrin 的回答指出了 UI 线程的死锁情况(这篇博文很好地描述了它,并提供了其他几个很好的提示),我做了一个简单的改变,但一直无法重现错误呢!
Thanks to @Afrin's answer pointing out the deadlock condition with the UI thread (This blog post does a good job describing it, and gives several other good tips), I made a simple change, and haven't been able to reproduce the error yet!
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
  try{
    byte[] buffer = new byte[port.BytesToRead];
    int rcvdBytes = port.Read(buffer, 0, buffer.Length);
    lock(locker){
      receivedBytes.AddRange(buffer);
    }
    ThreadPool.QueueUserWorkItem(handleReceivedBytes);
  } catch (Exception ex) {
    System.Diagnostics.Debug.WriteLine(ex.ToString());
    //put other, more interesting error handling here.
  }
}
private void handleReceivedBytes(object state)
{
  //Do the more interesting handling of the receivedBytes list here.
}
推荐答案
关闭它时它会挂起的原因是因为在您的 SerialPort 对象的事件处理程序中
The reason it would hang when you close it is because in the event handler of your SerialPort object
您正在将调用与主线程同步(通常通过调用调用).SerialPort 的 close 方法等待触发 DataReceived/Error/PinChanged 事件的 EventLoopRunner 线程终止.但是由于你自己在事件中的代码也在等待主线程响应,所以你遇到了死锁的情况.
You're synchronizing a call with the main thread (typically by calling invoke). SerialPort's close method waits for its EventLoopRunner thread which fires DataReceived/Error/PinChanged events to terminate. but since your own code in the event is also waiting for main thread to respond, you run into a dead lock situation.
解决方案:使用 begininvoke 而不是调用:https://connect.microsoft.com/VisualStudio/feedback/details/202137/serialport-close-hangs-the-application
solution: use begininvoke instead of invoke: https://connect.microsoft.com/VisualStudio/feedback/details/202137/serialport-close-hangs-the-application
参考:http://stackoverflow.com/a/3176959/146622
Microsoft 链接已损坏,因为他们已停用 Connect.试试 web.archive.org:https://web.archive.org/web/20111210024101/https://connect.microsoft.com/VisualStudio/feedback/details/202137/serialport-close-hangs-the-application
the Microsoft link is broken as they have retired Connect. try web.archive.org: https://web.archive.org/web/20111210024101/https://connect.microsoft.com/VisualStudio/feedback/details/202137/serialport-close-hangs-the-application
这篇关于C# Winform 在 SerialPort.Close 上冻结的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:C# Winform 在 SerialPort.Close 上冻结
				
        
 
            
        - 输入按键事件处理程序 2022-01-01
 - WebMatrix WebSecurity PasswordSalt 2022-01-01
 - 在哪里可以找到使用中的C#/XML文档注释的好例子? 2022-01-01
 - Web Api 中的 Swagger .netcore 3.1,使用 swagger UI 设置日期时间格式 2022-01-01
 - 带有服务/守护程序应用程序的 Microsoft Graph CSharp SDK 和 OneDrive for Business - 配额方面返回 null 2022-01-01
 - MoreLinq maxBy vs LINQ max + where 2022-01-01
 - C# 中多线程网络服务器的模式 2022-01-01
 - C#MongoDB使用Builders查找派生对象 2022-09-04
 - 如何用自己压缩一个 IEnumerable 2022-01-01
 - 良好实践:如何重用 .csproj 和 .sln 文件来为 CI 创建 2022-01-01
 
						
						
						
						
						
				
				
				
				