<i id='FLMGc'><tr id='FLMGc'><dt id='FLMGc'><q id='FLMGc'><span id='FLMGc'><b id='FLMGc'><form id='FLMGc'><ins id='FLMGc'></ins><ul id='FLMGc'></ul><sub id='FLMGc'></sub></form><legend id='FLMGc'></legend><bdo id='FLMGc'><pre id='FLMGc'><center id='FLMGc'></center></pre></bdo></b><th id='FLMGc'></th></span></q></dt></tr></i><div id='FLMGc'><tfoot id='FLMGc'></tfoot><dl id='FLMGc'><fieldset id='FLMGc'></fieldset></dl></div>

      <tfoot id='FLMGc'></tfoot>

    1. <small id='FLMGc'></small><noframes id='FLMGc'>

      <legend id='FLMGc'><style id='FLMGc'><dir id='FLMGc'><q id='FLMGc'></q></dir></style></legend>

        <bdo id='FLMGc'></bdo><ul id='FLMGc'></ul>

      C# Winform 在 SerialPort.Close 上冻结

      时间:2023-11-10

      • <i id='yhJmc'><tr id='yhJmc'><dt id='yhJmc'><q id='yhJmc'><span id='yhJmc'><b id='yhJmc'><form id='yhJmc'><ins id='yhJmc'></ins><ul id='yhJmc'></ul><sub id='yhJmc'></sub></form><legend id='yhJmc'></legend><bdo id='yhJmc'><pre id='yhJmc'><center id='yhJmc'></center></pre></bdo></b><th id='yhJmc'></th></span></q></dt></tr></i><div id='yhJmc'><tfoot id='yhJmc'></tfoot><dl id='yhJmc'><fieldset id='yhJmc'></fieldset></dl></div>
          <bdo id='yhJmc'></bdo><ul id='yhJmc'></ul>

          <small id='yhJmc'></small><noframes id='yhJmc'>

            <tbody id='yhJmc'></tbody>
            • <legend id='yhJmc'><style id='yhJmc'><dir id='yhJmc'><q id='yhJmc'></q></dir></style></legend><tfoot id='yhJmc'></tfoot>

                本文介绍了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# 中获取来电显示?

                相关文章

                1. <legend id='Pxayt'><style id='Pxayt'><dir id='Pxayt'><q id='Pxayt'></q></dir></style></legend>
                  <tfoot id='Pxayt'></tfoot>
                    <bdo id='Pxayt'></bdo><ul id='Pxayt'></ul>

                2. <small id='Pxayt'></small><noframes id='Pxayt'>

                3. <i id='Pxayt'><tr id='Pxayt'><dt id='Pxayt'><q id='Pxayt'><span id='Pxayt'><b id='Pxayt'><form id='Pxayt'><ins id='Pxayt'></ins><ul id='Pxayt'></ul><sub id='Pxayt'></sub></form><legend id='Pxayt'></legend><bdo id='Pxayt'><pre id='Pxayt'><center id='Pxayt'></center></pre></bdo></b><th id='Pxayt'></th></span></q></dt></tr></i><div id='Pxayt'><tfoot id='Pxayt'></tfoot><dl id='Pxayt'><fieldset id='Pxayt'></fieldset></dl></div>