今天寫了一個串口通訊掃碼槍驅動,程序運行后,不出意外的全線崩潰,開始了漫長的排查之旅,具體情況報錯如下:
解決未處理 System.ObjectDisposedException
Message=已關閉 Safe handle
Source=mscorlib
ObjectName=""
StackTrace:
在 System.Runtime.InteropServices.SafeHandle.DangerousAddRef(Boolean& success)
在 System.StubHelpers.StubHelpers.SafeHandleAddRef(SafeHandle pHandle, Boolean& success)
在 Microsoft.Win32.UnsafeNativeMethods.GetOverlappedResult(SafeFileHandle hFile, NativeOverlapped* lpOverlapped, Int32& lpNumberOfBytesTransferred, Boolean bWait)
在 System.IO.Ports.SerialStream.EventLoopRunner.WaitForCommEvent()
在 System.Threading.ThreadHelper.ThreadStart_Context(Object state)
在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
在 System.Threading.ThreadHelper.ThreadStart()
真的真的很無語,程序正常跑了一會,也能捉到數據,突然它就中風了,數據捉不到了,也沒有任何報錯。
逼不得已程序重新解包重裝,到處打斷點一步一步調試。最后發現當這個BUG出現時,程序直接崩潰,無法跟蹤到錯誤代碼位置。
最后意識到SerialPort類引起的問題,可能是在已釋放的SerialPort對象上嘗試進行操作導致的問題。
- 思路一:
- 為了解決這個問題,可以在使用完SerialPort對象后,確保正確地釋放和關閉它。
- 但是呀,我的是掃碼槍啊,串口必須一直打開,怎么可能關閉它,于是這個方案立馬放棄。
- 思路二:
- 我在使用SerialPort的時候可以檢查它的狀態呀確保在處理數據之前,串口仍然處于打開狀態。這樣可以避免在已關閉的串口上進行操作,從而減少System.ObjectDisposedException異常的發生。
- 說干就干,代碼增加一行 if 判斷:
if (!serialPort.IsOpen){serialPort.Open();}
- 思路三:
- 在一個函數內利用SerialPort創建了串口通信實例后,沒有將該實例放入任何其他容器中進行緩存,從而也會導致了上述崩潰BUG的產生。
- 那我就修改代碼:將該實例放入了一個全局變量List<通信客戶端>集合,下面的代碼分別放到對應位置就行。
//這個作為全局變量就聲明創建
public List<SerialPort> PortModels = new List<SerialPort>();//這個在實例化對象后封裝
PortModels.Add(SerialPort);/
哈哈哈,經過以上幾步該BUG終于得以解決,家人們高歌萬歲吧!!!