2009-10-26 80 views
1

我一直有這個問題一段時間了,從來沒有真正能夠解決它。只有在使用SendAsync/ReceiveAsync方法而不是Begin/EndSend套接字方法進行異步操作時纔會出現此問題。.Net套接字 - >拋出System.InvalidOperationException

如果有一個相當複雜的tcp套接字庫,並且意味着用SendAsync替換BeginSend方法,但由於我遇到的問題,我總是不得不放棄它。我的套接字服務器正在處理大於1000個客戶端連接的壓力劇烈的情況,並持續推動超過100mbit /秒,我想利用SendAsync方法,所以我沒有IAsyncResult分配開銷。

不管怎麼說,只要我只是發送/接收數據,一切都會正常工作,但是在服務器試圖斷開/關閉客戶端的高壓力情況下,我偶爾會遇到以下異常:

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: 

我不能在任何地方捕獲這個異常,因爲它似乎在.NET框架內發生,我不能做它崩潰我的服務器什麼。

因爲這隻發生在我打電話給我的關機程序時,我猜它與在套接字上調用Shutdown有關,而它仍然有一個讀/寫程序掛起。 但是,我也嘗試延遲調用關機,直到所有讀/寫Send/ReceiveAsync調用都返回並在此之後調用關閉,但這也沒有幫助。

以下是我嘗試關閉套接字:

 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); 
               } 
              } 
             }); 
    } 

回答

2

好了,由於某種原因,總是幫助我要問的問題,因爲我往往總是後不久弄清楚事情:/

看來, asyncSendArgs.SetBuffer(null,0,0);是罪魁禍首。 儘管在調用InternalDisconnect之前,另一段代碼應該確保沒有未完成的異步操作,但似乎仍然存在並在使用中更改緩衝區肯定會導致問題。 到目前爲止,我一直在進行15分鐘的重壓力測試,一切看起來都很好(在我一分鐘內總是得到這種異常之前)。我會讓它多跑一段時間,並希望那樣做。

+1

您好Tom Frey, 您是如何解決該異常的? 我現在面臨的例外 – 2011-01-22 16:27:01

相關問題