簡體   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