ObjectDisposedExecption после закрытия.NET SerialPort

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

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

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

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

System.ObjectDisposedException: безопасный дескриптор закрыт
     в System.Runtime.InteropServices.SafeHandle.DangerousAddRef(логическое значение и успех)
     at System.StubHelpers.StubHelpers.SafeHandleAddRef(SafeHandle pHandle, Boolean& success)
     в 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 executeContext, обратный вызов ContextCallback, состояние объекта, логическое значение ignoreSyncCtx)
     в System.Threading.ExecutionContext.Run(ExecutionContext executeContext, обратный вызов 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, чтобы определить, когда я избавляюсь от чего-то, чего не должно быть, но я достигаю этой точки останова десятки раз. Три раза звонил мой единственный звонок SerialPort.Close, когда я закончу с использованием последовательного устройства, и около половины остальных находятся в потоке GC. Остальная часть связана с элементами пользовательского интерфейса WPF.

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

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

2 ответа

Решение

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

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

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

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

Другие вопросы по тегам