gpt4 book ai didi

C# Winform 在 SerialPort.Close 上卡住

转载 作者:太空狗 更新时间:2023-10-29 18:16:41 26 4
gpt4 key购买 nike

我有一个 winform 程序,它在 SerialPort 上执行一些异步 IO。但是,我会定期遇到程序在 SerialPort.Close() 调用时卡住的问题,这似乎是随机的。

我认为这是一个线程安全问题,但如果是,我不确定如何解决。我尝试使用端口打开/关闭功能添加/删除异步 DataReceived 处理程序并丢弃端口上的输入和输出缓冲区,但它似乎没有做任何事情。我认为重要的 SerialPort 代码如下:

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 线程的死锁情况(This blog post 很好地描述了它,并给出了其他几个很好的提示),我做了一个简单的更改,但无法重现错误呢!

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 对象的事件处理程序中

您正在与主线程同步调用(通常通过调用 invoke)。 SerialPort 的关闭方法等待触发 DataReceived/Error/PinChanged 事件的 EventLoopRunner 线程终止。但是由于事件中您自己的代码也在等待主线程响应,因此您遇到了死锁情况。

解决方案:使用 begininvoke 而不是调用: 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

关于C# Winform 在 SerialPort.Close 上卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8843301/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com