COM1 に接続されたデバイスと通信するために .NET 4 SerialPort オブジェクトを使用しています。
デバイスの操作が完了したら、SerialPort で Close を呼び出します。私は Dispose とは呼びませんが、ここでは Close と Dispose は同義だと思います。
通常、これで問題なく動作します。
ただし、しばらくしてから次の例外が発生することがあります (私が確認した時間は 5 ミリ秒から 175 ミリ秒の範囲です)。
System.ObjectDisposedException: 安全なハンドルが閉じられました System.Runtime.InteropServices.SafeHandle.DangerousAddRef (ブール値 & 成功) で System.StubHelpers.StubHelpers.SafeHandleAddRef (SafeHandle pHandle、ブール値 & 成功) で Microsoft.Win32.UnsafeNativeMethods.GetOverlappedResult (SafeFileHandle hFile、NativeOverlapped* lpOverlapped、Int32 & lpNumberOfBytesTransferred、ブール値の bWait) で System.IO.Ports.SerialStream.EventLoopRunner.WaitForCommEvent() で System.Threading.ThreadHelper.ThreadStart_Context (オブジェクトの状態) で System.Threading.ExecutionContext.Run (ExecutionContext executionContext、ContextCallback コールバック、オブジェクトの状態、ブール値の ignoreSyncCtx) で System.Threading.ExecutionContext.Run (ExecutionContext executionContext、ContextCallback コールバック、オブジェクトの状態) で System.Threading.ThreadHelper.ThreadStart() で
このスタックには私のコードはありません。
http://blog.zachsaw.com/2010/07/serialport-ioexception-workaround-in-c.htmlを見つけましたが、そこでの解決策は機能しませんでした。さらに調べてみると、問題はIOException
ではなくObjectDisposedException
です。
USB-to-serial デバイスが取り外されたときに観察される問題に関する投稿が多数ありますが、COM1 はオンボードであるため、予期せず消えることはありません。
ここの問題も私の問題ではありません。SerialPort は使用中は保持され、デバイスとの通信が終了したときにのみ閉じられます。(完了すると、デバイスはそれ以上データを送信しない状態になります。)
SLaksは、 への入り口にブレークポイントを設定して、SafeHandle.Dispose
処分すべきではないものをいつ処分するかを判断することを提案していますが、私はそのブレークポイントを何十回も打ちます。シリアル デバイスの使用が終了すると、への 1 回の呼び出しで 3 回呼び出されSerialPort.Close
、残りの約半分は GC スレッドにあります。残りは、WPF UI 要素に関連しているようです。
私は今途方に暮れています。ここからどこへ行けばいいですか?
どの SafeHandle がどのオブジェクトに属しているかを判断する方法はありますか?
SerialPort を適切にシャットダウンする必要がある Close 以外の呪文はありますか?