繁体   English   中英

SerialPort.Close() 问题 - 无法使用任务管理器关闭应用程序!

[英]SerialPort.Close() problem - can't shut down the application with the taskmanager!

这是一个主要问题——我在这里的应用程序中使用串行端口,我通过打开然后再次关闭端口来轮询连接设备的状态。

如果设备出现故障,有时 SerialPort.Close() - 方法永远不会返回,这确实是一个表演障碍。

最糟糕的是,即使使用任务管理器关闭应用程序失败,它也不起作用(或者偶然被禁止)。

附加设备是模拟 COM3 的 POS 打印机 (USB),它是爱普生 TM-T88IV(非常好的 model,顺便说一句)。

你们中有人有这方面的经验吗?

不建议反复打开和关闭端口。 有关SerialPort.Close(),请查看MSDN Library文章中的“备注”部分。 有一个后台线程需要在再次打开端口之前关闭,这需要时间。 时间量是不可预测的。

如果DataReceived事件处理程序当前正在运行,则Close()方法很容易死锁。 获取死锁的最典型方法是在事件处理程序中调用Control.Invoke()。 确保在阻止或需要线程上下文切换的事件处理程序中不使用任何代码。 使用BeginInvoke()很好。

无法终止程序是由串行端口设备驱动程序中的问题引起的。 启动Taskmgr.exe,Process选项卡,View + Select Columns并勾选“Handles”。 如果在杀死程序后,您看到Handles列显示1,则串行端口驱动程序将挂起到未完成的I / O请求。 在退出所有内核模式线程之前,该进程无法终止。

除了希望更新驱动程序或切换到其他供应商之外,您无法对该特定问题做些什么。 特别是USB串口仿真器因糟糕的设备驱动程序而臭名昭着。 你把它从停车场取出并用你的车多次运行就可以摆脱这样的麻烦制造者。

USB仿真器的另一个典型问题是它们在使用时很容易断开连接。 这与Windows正在写入时将闪存驱动器从插槽中抽出一样有效。 这也是一个让设备驱动程序挂起的好方法当4.0版本之前的.NET版本在后台线程中遭受心脏病发作时,设备会突然消失。 升级之后,连接器旁边的一个小符号显示“在使用时不要断开连接!” 是一个实用的解决方法。 无论如何他们会在几次之后对它感到厌倦。

Fwiw,这就是为什么存在“安全删除硬件”托盘图标的原因。 你会得到一个坚实的“不要做!” 只要您的程序正在使用该端口,就会出错。 但是,当然,操作系统无法让用户真正使用它。 Apple拥有一项技术专利 ,使其具有故障安全性,检测设备上用户的手指:)

在.Net 4.0之前,USB到SerialPort设备(崩溃程序/系统等)可能出现很多问题。 通过在端口处于活动状态时拉动USB适配器可以轻松测试错误。

最近我使用.Net 4.0运行了一些测试,它是固定的(肯定有所改进)??? 测试是通过带有环回的USB SerialPort进行简单的RX / TX,并在使用时拔出USB适配器。 我的程序没有崩溃,我能够重新打开端口! 这是一项重大改进。

虽然有时会出现SerialPort.Close方法死锁的问题,但这不应该阻止任务管理器终止您的进程。 如果你不能杀死你的进程,这几乎肯定是由于USB串行驱动程序中的一个错误。 不幸的是,您的选择很可能是:

  • 不要轮询设备状态
  • 让供应商修复错误
  • 通过找出一种在不访问串行端口的情况下轮询设备状态的方法来解决问题
  • 通过其他方法(可能是直接的USB操作)访问设备来解决问题

不可能?

我有一个想法:在数据接收事件中放置一个标志,从内部关闭serialcom! 简单!

现在尝试我自己

如何使用BackGround线程轮询设备,以便它不会阻止您的应用程序退出?

这是一个链接,其中包含许多此问题和(潜在)解决方案的其他链接:

http://www.vbforums.com/showthread.php?t=558000

你可以使用这个:

private void Form_FormClosing(object sender, FormClosingEventArgs e)
{

    if (_serialPort.IsOpen)
    {
        e.Cancel = true; //cancel the fom closing
        Thread CloseDown = new Thread(new ThreadStart(CloseSerialOnExit)); //close port in new thread to avoid hang
        CloseDown.Start(); //close port in new thread to avoid hang
    }
}

private void CloseSerialOnExit()
{
    try
    {
        _serialPort.Close(); //close the serial port
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message); //catch any serial port closing error messages
    }
    this.Invoke(new EventHandler(NowClose)); //now close back in the main thread
}

 private void NowClose(object sender, EventArgs e)
{
    this.Close(); //now close the form
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM