12

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 以外の呪文はありますか?

4

2 に答える 2

4

私もこの問題を抱えていましたが、次の 2 つのルールを使い始めて以来、二度と見たことはありません。

  1. 常に Close() を呼び出してから Dispose() を呼び出します。
  2. SerialPort オブジェクトを再利用しないでください。ポートを再度開く必要がある場合は、常に新しいオブジェクトを作成してください。

私は知っています、彼らはあまりニュースではありませんが、それは私のために働いています.

于 2011-08-18T21:33:40.827 に答える
0

破棄への呼び出しは文書化された動作です(こちらを参照)-クローズ後に(おそらく別のスレッドで)読み取り/書き込みを試みていると思います。呼び出しを別のクラスにラップし、「クローズ」フラグを設定することをお勧めします。そうすれば、問題をかなり早く見つけることができるはずです。

于 2011-08-18T20:49:38.790 に答える