首页 > 解决方案 > ObjectDisposedException SslStream 和 TcpClient

问题描述

我正在使用带有 SslStream 的 TcpClient。一般来说,一切正常,但我们偶尔会收到崩溃日志。它似乎来自不稳定的网络连接,尽管尝试创建“意外情况”,但很遗憾我无法在本地重现它:

情况是这样的:

我这样称呼 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 回调函数中,我在 SslStream 上调用 EndRead,它会抛出一个异常,然后处理:

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 事件之一中?如果是这样,处理此问题的最佳实践方法是什么?基本上我需要事件处理程序中的一些逻辑来确定如果收到此特定错误,软件不应关闭?

标签: c#.netsockets

解决方案


推荐阅读