C# 带有SerialPort的Windows窗体-关闭窗体后应用程序挂起

C# 带有SerialPort的Windows窗体-关闭窗体后应用程序挂起,c#,multithreading,arduino,serial-port,C#,Multithreading,Arduino,Serial Port,我有一个windows窗体应用程序,可以连接到Arduino板。当我想关闭它时,它将保持打开状态,直到我停止调试模式。当我在VisualStudio中运行程序时,以及当我单独运行exe文件时,会发生这种情况,我必须从任务管理器中停止它 我尝试了FormClosing和FormClosing事件,但结果是一样的。我唯一想到的是,出现这种问题是因为我在我的SerialPort的datareceived事件中为我的控件使用了许多Invoke函数。我这样做是因为我需要对表单控件进行线程安全调用。以下是我

我有一个windows窗体应用程序,可以连接到Arduino板。当我想关闭它时,它将保持打开状态,直到我停止调试模式。当我在VisualStudio中运行程序时,以及当我单独运行
exe
文件时,会发生这种情况,我必须从任务管理器中停止它

我尝试了
FormClosing
FormClosing
事件,但结果是一样的。我唯一想到的是,出现这种问题是因为我在我的
SerialPort
datareceived
事件中为我的控件使用了许多
Invoke
函数。我这样做是因为我需要对表单控件进行线程安全调用。以下是我代码的一部分:

private void spArduino_DataReceived(对象发送方,System.IO.Ports.SerialDataReceivedEventArgs e)
{
如果(spArduino.BytesToRead>0)
{
字符串数据=spArduino.ReadLine().Replace(“\r”,”);
if(数据启动方式(“当前温度:))
{
if(lbTemprature.invokererequired)
{
lbTemprature.Invoke(新方法调用器(委托{
lbTemprature.Text=“室温”+数据。删除(0,9)+“摄氏度”;
}));
}
}
}
}
///////
私有无效监视\u FormClosing(对象发送方,FormClosingEventArgs e)
{
尝试
{
spArduino.WriteLine(“清晰”);
spArduino.Close();
}
捕获(例外)
{
MessageBox.Show(“errorclose”);
}
}
这将显示在我的输出中(VisualStudio)

在我停止程序之前,它一直这样


有人能帮我了解我的问题在哪里以及如何解决吗?

看看你是如何清理串行设备的。尝试取消订阅活动(即,
-=spArduino\u DataReceived
)。引用可能会阻止垃圾收集并在关闭后保持窗体的活动状态。

在主UI线程之外的单独线程上触发
SerialPort.DataReceived
事件,这就是为什么在更新UI时需要调用
lbTemprature.Invoke
方法的原因

关闭窗体而不关闭端口 如果在不关闭端口的情况下关闭表单,则在关闭表单时,在释放表单后可能会触发
DataReceived
事件,这将在尝试更新UI时导致异常

在关闭窗体之前关闭端口 如果在关闭窗体之前关闭端口(例如在
FormClosing
事件中),则可能会遇到死锁,因为主UI线程中的
SerialPort.close()
等待触发
DataReceived
事件的线程完成事件,调用
lbTemprature.Invoke
时,
DataReceived
事件正在等待UI线程。这可能是导致窗体释放的原因

解决方案 解决方案可以调用
lbTemprature.BeginInvoke
,以避免死锁。这可能还不够,因为在处理表单后,
BeginInvoke
仍然可以运行,并导致期望值。可能需要向
表单.IsDisposed
属性添加检查

if (lbTemprature.InvokeRequired)
{
    lbTemprature.BeginInvoke(new MethodInvoker(delegate
    {
        if (!this.IsDisposed)
        {
            lbTemprature.Text = "Room temprature  " + data.Remove(0,9) + "°C";
        }
    }));
}

尝试注释掉spArduino_DataReceived中的所有内容,运行应用程序并尝试关闭。如果是,您与您的代表之间存在问题。猜测:
lbTemprature.Invoke
无法正常工作,
spArduino
中的完整任务失败并阻塞UI。
if (lbTemprature.InvokeRequired)
{
    lbTemprature.BeginInvoke(new MethodInvoker(delegate
    {
        if (!this.IsDisposed)
        {
            lbTemprature.Text = "Room temprature  " + data.Remove(0,9) + "°C";
        }
    }));
}