2011-09-08 58 views
7

有時候,我的一些集成測試與上述消息失敗。我正在使用下面的代碼準備端口。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的狀態,以便新線程/進程可以再次訪問它?

感謝,

理查德

回答

11

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

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

+0

感謝漢斯 - 這隻發生在不同測試過程開始的測試中。 –

2

我不能看到你關閉端口。

對我來說,問題不在這裏(即使你應該重構位代碼),但可能是你在呼喚port.Open();當端口仍然是打開

從MSDN

只有一個打開的連接可以每個SerialPort對象都存在。

(我不能告訴你爲什麼,因爲我沒有足夠的信息)請記住關閉方法需要一些時間來真正關閉端口,實際上你應該阻塞主線程直到端口有被關閉(可能使用的Thread.join)

從MSDN

任何應用最好的做法就是等待一定的時間試圖調用Open方法之前調用Close方法之後,作爲端口可能不會立即關閉。

更多信息

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

+0

@Massimilano - 謝謝你的回答。休眠300ms後(當打開失敗時引發異常),端口在catch塊中關閉。 –

+0

我可以看到,但只有在引發異常時才關閉端口。 如果port.Open()不會拋出異常,則不會執行.Close() –

+0

對不起,如果我不清楚。開放失敗的原因是由於正在拋出UnauthorizedAccessException(這是我試圖關閉的原因)。 –

4

我經常在我實例化一個串口之前驗證端口是否關閉。這有助於在不關閉串口的情況下停止調試代碼。在繼續執行代碼之前,您也應該在打開或關閉端口後等待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); 
     } 
0

GC.SuppressFinalizeGC.ReRegisterForFinalize應該叫路過一個串口實例BaseStream屬性作爲參數,而不僅僅是一個串口實例。

相關問題