【发布时间】:2011-01-22 10:13:22
【问题描述】:
这个问题我已经有一段时间了,而且从来没有真正能够解决它。仅当我使用 SendAsync/ReceiveAsync 方法而不是 Begin/EndSend 套接字方法进行异步操作时才会出现此问题。
如果有一个相当复杂的 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 有关,而它仍然有一个读/写过程未决。 但是,我也尝试延迟调用 shutdown 直到所有读/写 Send/ReceiveAsync 调用都返回并在此之后调用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);
}
}
});
}
【问题讨论】:
标签: c# sockets asynchronous tcp