我有这个问题已经有一段时间了,从来没有真正能够解决它。只有在使用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);
}
}
});
}