簡體   English   中英

SerialPort UnauthorizedAccessException

[英]SerialPort UnauthorizedAccessException

有時我的某些集成測試會因上述消息而失敗。 我正在使用下面的代碼來准備端口。

            for(int i = 0; i < 5; i++)
            {
                try
                {
                    port.Open();
                    if (port.IsOpen)
                        break;
                }
                catch (Exception e)
                {
                    try
                    {
                        port.Close();
                    }
                    catch (Exception)
                    {}
                    Thread.Sleep(300);
                }
            }   

我的假設是因為它不能阻止端口的當前線程(因為它會嘗試關閉它),它必須是另一個沒有正確清理而死的線程或進程(其他測試之一 - 沒有其他訪問這個港口)。 有沒有辦法重置SerialPort的狀態,以便新的線程/進程可以再次訪問它?

謝謝,

理查德

這是SerialPort類中的一個缺陷,它使用內部幫助程序線程來等待端口上的事件。 DataReceived,PinChanged和ErrorReceived事件的來源。 該缺陷在Close()方法實現中,它不等待這個輔助線程終止。 這需要時間,確切的時間量是不可預測的,並且當機器特別繁忙時可能需要很多秒。 在發生這種情況之前,物理端口不會關閉,在線程退出炸彈之前打開端口並使用“已在使用的端口”例外。 你得到的那個。 因此,睡眠300毫秒是不夠的。

這通常不是問題,串口不是可共享的設備。 關閉串口而不退出程序是危險的,另一個進程可能會竊取端口。 當您嘗試再次打開它時也會給您這個例外。 通常的做法是在應用程序啟動時打開端口,而不是關閉它直到它終止。

在我實例化串口之前,我經常驗證端口是否已關閉。 如果在不關閉串行端口的情況下停止調試代碼,這將有所幫 此外,在繼續使用代碼之前,您應該在打開或關閉端口后等待250毫秒。

try
        {
            if ((m_SerialPort != null))
            {
                if (m_SerialPort.IsOpen)
                {
                    m_SerialPort.Close();
                }
             }
             m_SerialPort = new SerialPort(portName, dataRate, parity, databits, stopBits.One);
             m_SerialPort.Open();
             if (!m_SerialPort.IsOpen)
             {
                 MessageBox.Show(string.Concat(portName, " failed to open"));
             }
         }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }

我看不到你關閉港口的位置。

我的問題不在這里(即使你應該重構一下代碼),但可能你正在調用port.Open(); 當端口仍然打開時

來自MSDN

每個SerialPort對象只能存在一個打開的連接。

(我不能告訴你為什么,因為我沒有足夠的信息)熊也記住close方法需要一些時間來實際關閉端口實際上你應該阻塞主線程直到端口關閉(也許使用的Thread.join)

來自MSDN

任何應用程序的最佳實踐是在嘗試調用Open方法之前等待一段時間后再調用Close方法,因為端口可能不會立即關閉。

了解更多信息

http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.open.aspx

應該調用GC.SuppressFinalizeGC.ReRegisterForFinalize ,將SerialPort實例BaseStream屬性作為參數傳遞,而不僅僅是SerialPort實例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM