ObjectDisposedExecption после закрытия .NET SerialPort - PullRequest
10 голосов
/ 19 августа 2011

Я использую объект .NET 4 SerialPort для связи с устройством, подключенным к COM1.

Когда я закончу с устройством, я вызываю Close на SerialPort. Я не вызываю Dispose, но я считаю, что Close и Dispose здесь являются синонимами.

Обычно это работает просто отлично.

Иногда, однако, иногда я получаю следующее исключение (время, которое я видел, колеблется от 5 мс до 175 мс):

System.ObjectDisposedException: Safe handle has been closed
     at System.Runtime.InteropServices.SafeHandle.DangerousAddRef(Boolean& success)
     at System.StubHelpers.StubHelpers.SafeHandleAddRef(SafeHandle pHandle, Boolean& success)
     at Microsoft.Win32.UnsafeNativeMethods.GetOverlappedResult(SafeFileHandle hFile, NativeOverlapped* lpOverlapped, Int32& lpNumberOfBytesTransferred, Boolean bWait)
     at System.IO.Ports.SerialStream.EventLoopRunner.WaitForCommEvent()
     at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
     at 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, чтобы определить, когда я избавляюсь от того, чего не должен быть, но я бью эту точку останова десятки раз. Мой одиночный вызов три раза вызывается на SerialPort.Close, когда я использую последовательное устройство, и около половины остальных находятся в потоке GC. Остальная часть, похоже, связана с элементами пользовательского интерфейса WPF.

Я сейчас в растерянности. Куда мне идти отсюда?

Есть ли способ определить, какой SafeHandle принадлежит какому объекту, так что я могу быть уверен, что не избавлюсь от него неожиданно?
Есть ли какие-нибудь заклинания, кроме Close, мне нужно правильно отключить SerialPort?

Ответы [ 2 ]

4 голосов
/ 19 августа 2011

У меня тоже была эта проблема, и с тех пор, как я начал использовать следующие два правила, я никогда не видел ее снова.

  1. Всегда вызывайте Close (), а затем Dispose ().
  2. Никогда не используйте повторно объект SerialPort, всегда создавайте новый, когда порт должен быть открыт заново.

Я знаю, они не так много новостей, но это работает для меня.

0 голосов
/ 19 августа 2011

Вызов disposed - задокументированное поведение ( см. Здесь ) - я полагаю, вы пытаетесь читать / писать после закрытия (возможно, в другой теме).Я бы предложил обернуть вызовы в отдельный класс и установить флаг «closed».Тогда вы сможете быстро найти проблему.

...