ObjectDisposedException SslStream и TcpClient - PullRequest
0 голосов
/ 01 ноября 2018

Я использую TcpClient с SslStream. В целом все работает нормально, но мы время от времени получаем журналы аварий. Кажется, это происходит из-за нестабильных сетевых подключений, и я, к сожалению, не могу воспроизвести его локально, несмотря на попытки создать «непредвиденные обстоятельства»:

  • с использованием Fiddler для репликации очень медленного сетевого подключения
  • уничтожение серверного приложения при отправке данных
  • отключение сетевых кабелей

Ситуация такова:

Я называю BeginRead так:

_tcpClientStream.BeginRead(receiveBuffer, 0, receiveBuffer.Length, pfnCallBack, null);

И тогда EndRead вызывается так:

iRx = _tcpClientStream.EndRead(asyn);

Единственное место, где используется iRx, - это скопировать полученные данные в новый массив:

var bytes = new byte[iRx];
Array.Copy(receiveBuffer, bytes, iRx);

В функции обратного вызова OnDataReceived я вызываю EndRead для SslStream, который выдает обработанное исключение:

Error in OnDataReceived System.IO.IOException: The read operation failed, see inner exception. ---> System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: size
   at System.Net.Sockets.NetworkStream.BeginRead(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state)
   at System.Net.FixedSizeReader.StartReading()
   at System.Net.FixedSizeReader.ReadCallback(IAsyncResult transportResult)
   --- End of inner exception stack trace ---
   at System.Net.Security._SslStream.EndRead(IAsyncResult asyncResult)
   at System.Net.Security.SslStream.EndRead(IAsyncResult asyncResult)
   at XXXXXXX.OnDataRecevied(IAsyncResult asyn)

Обычно это не проблема - это исключение перехватывается, и TcpClient закрывается и повторно запускается, чтобы попытаться восстановить соединение.

Однако в этом случае возникает второе исключение, которое генерируется одним из обработчиков ошибок UnhandledException:

AppDomain.CurrentDomain.UnhandledException
Current.DispatcherUnhandledException
Current.Dispatcher.UnhandledException
TaskScheduler.UnobservedTaskException

Эта трассировка стека выглядит так:

System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Net.Sockets.NetworkStream'.
   at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)
   at System.Net.FixedSizeReader.ReadCallback(IAsyncResult transportResult)
   at System.Net.LazyAsyncResult.Complete(IntPtr userToken)
   at System.Net.ContextAwareResult.CompleteCallback(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Net.ContextAwareResult.Complete(IntPtr userToken)
   at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
   at System.Net.Sockets.BaseOverlappedAsyncResult.CompletionPortCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
   at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)

Мы обрабатываем этот тип необработанной ошибки, чтобы показать пользователю сообщение о том, что произошла фатальная ошибка, и программное обеспечение должно закрыться.

Мои вопросы:

  1. Кто-нибудь когда-либо видел эту ошибку раньше и смог воспроизвести точное исключение вне диапазона, которое я получаю? Несмотря на мои попытки воссоздать проблему (используя методы, описанные выше), я не могу воссоздать исключение, это всегда более стандартное исключение Socket IO:

    Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
       at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult)
       at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)
       --- End of inner exception stack trace ---
       at System.Net.Security._SslStream.EndRead(IAsyncResult asyncResult)
       at System.Net.Security.SslStream.EndRead(IAsyncResult asyncResult)
       at XXXXXXXXX.OnDataRecevied(IAsyncResult asyn)
    
  2. Можно ли как-то обработать это исключение в моем коде Socket или оно всегда будет появляться в одном из этих событий UnhandledException? Если так, то каков наилучший способ справиться с этим? В основном мне нужна логика в обработчике событий, чтобы определить, что программное обеспечение не должно закрываться, если получена эта конкретная ошибка?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...