代码之家  ›  专栏  ›  技术社区  ›  TJF

.Net套接字->抛出System.InvalidOperationException

  •  1
  • TJF  · 技术社区  · 16 年前

    我有这个问题已经有一段时间了,从来没有真正能够解决它。只有在使用SendAsync/ReceiveAsync方法而不是Begin/EndSend套接字方法进行异步操作时,才会出现此问题。

    无论如何,只要我只是发送/接收数据,一切都正常,但是在高压力情况下,当服务器尝试断开/关闭客户端时,我偶尔会遇到以下异常:

        System.InvalidOperationException was unhandled
      Message=Cannot apply a context that has been marshaled across AppDomains, that was not acquired through a Capture operation or that has already been the argument to a Set call.
      Source=mscorlib
      StackTrace:
           at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
           at System.Net.Sockets.SocketAsyncEventArgs.FinishOperationSuccess(SocketError socketError, Int32 bytesTransferred, SocketFlags flags)
           at System.Net.Sockets.SocketAsyncEventArgs.CompletionPortCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
           at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
      InnerException: 
    

    但是,我也尝试延迟调用shutdown,直到所有读/写发送/接收异步调用都返回,然后再调用shutdown,但这也没有帮助。

    以下是我如何尝试关闭套接字:

            private void InternalDisconnect(SocketError socketError)
        {
            lock (shutdownLock)
            {
                if (isShutdown)
                    return;
    
                isShutdown = true;
            }
    
            allowSend = false;
            SocketError = socketError;
    
            ThreadPool.QueueUserWorkItem(delegate
                                             {
                                                 lock (padLock)
                                                 {
                                                     try
                                                     {
                                                         if (TcpSocketStatus == TcpSocketStatus.Disconnected)
                                                             return;
    
                                                         TcpSocketStatus = TcpSocketStatus.Disconnecting;
    
                                                         if (asyncSendArgs != null)
                                                         {
                                                             asyncSendArgs.Completed -= SendCompleted;
                                                             asyncSendArgs.SetBuffer(null, 0, 0);
                                                             asyncSendArgs.Dispose();
                                                         }
    
                                                         if (asyncReceiveArgs != null)
                                                         {
                                                             asyncReceiveArgs.Completed -= ReceiveCompleted;
                                                             asyncReceiveArgs.SetBuffer(null, 0, 0);
                                                             asyncReceiveArgs.Dispose();
                                                         }
    
                                                         try
                                                         {
                                                             bufferedSender.Clear();
    
                                                             Socket.Shutdown(SocketShutdown.Both);
    
                                                             if (Socket.Connected)
                                                             {
                                                                 Socket.Disconnect(true);
                                                             }
                                                         }
                                                         catch
                                                         {
                                                         }
    
                                                         try
                                                         {
                                                             Socket.Close();
                                                         }
                                                         catch
                                                         {
                                                         }
    
                                                         TcpSocketStatus = TcpSocketStatus.Disconnected;
    
                                                         if (socketError != SocketError.Success)
                                                         {
                                                             if (log.IsDebugEnabled)
                                                                 log.Debug("SocketDisconnected\tSocketError:{0}", socketError);
                                                         }
                                                         else
                                                         {
                                                             if (log.IsDebugEnabled)
                                                                 log.Debug("SocketDisconnected");
                                                         }
    
                                                         DisconnectTime = DateTime.UtcNow;
    
                                                         if (TcpSocketDisconnected != null)
                                                             TcpSocketDisconnected(this);
                                                     }
                                                     catch (Exception ex)
                                                     {
                                                         log.ErrorException("InternalDisconnect", ex);
                                                     }
                                                 }
                                             });
        }
    
    1 回复  |  直到 16 年前
        1
  •  2
  •   TJF    16 年前

    好吧,出于某种原因,问问题总是对我有帮助,因为我总是在很短的时间内就想清楚事情:/

    似乎asyncSendArgs.SetBuffer(null,0,0);是罪魁祸首。 到目前为止,我已经进行了15分钟的高强度压力测试,一切似乎都很好(在我总是在一分钟内出现异常之前)。我会让它再运行一段时间,并希望这样做。

    推荐文章