http://msdn.microsoft.com/en-us/library/system.net.sockets.socketasynceventargs.aspx.net asíncrono toma tiempo de espera de comprobación de hilo de seguridad
A partir de lo anterior ejemplo de MSDN Estoy tratando de escribir un cheque de tiempo de espera que se cerrará sockets de cliente inactivas y liberar recursos.
Esto es lo que se me ocurrió. Pero no estoy seguro si es completamente seguro para subprocesos y si hay una mejor manera de hacerlo. Espero que alguien pueda dar algunos consejos.
void IO_Completed(object sender, SocketAsyncEventArgs e)
{
if (e.SocketError != SocketError.Success)
{
CloseClientSocket(e);
return;
}
if (1 < Interlocked.CompareExchange(ref token.Status, 1, 0))
return;
switch (e.LastOperation)
{
case SocketAsyncOperation.Receive:
ProcessReceive(e);
break;
...
}
token.LastActive = Environment.TickCount;
Interlocked.CompareExchange(ref token.Status, 0, 1);
}
void ProcessReceive(SocketAsyncEventArgs e)
{
AsyncUserToken token = (AsyncUserToken)e.UserToken;
if (e.BytesTransferred > 0)
if (!token.Socket.SendAsync(e))
ProcessSend(e);
else
CloseClientSocket(e);
}
void ProcessSend(SocketAsyncEventArgs e)
{
AsyncUserToken token = (AsyncUserToken)e.UserToken;
if (!token.Socket.ReceiveAsync(e))
ProcessReceive(e);
}
TimeoutCheck se ejecutará una vez cada 20 segundos. allReadWriteArgs es una matriz con todos los SocketAsyncEventArgs. Después de cerrar el socket, IO_Completed se invocará con SocketError.OperationAborted.
void TimeoutCheck(object state)
{
AsyncUserToken token;
int timeout = Environment.TickCount - 20000;
for (int i = 0; i < allReadWriteArgs.Length; i++)
{
token = (AsyncUserToken)allReadWriteArgs[i].UserToken;
if (token.LastActive < timeout)
if (0 == Interlocked.CompareExchange(ref token.Status, 2, 0))
Interlocked.Exchange(ref token.Socket, null).Close();
}
}
void CloseClientSocket(SocketAsyncEventArgs e)
{
AsyncUserToken token = e.UserToken as AsyncUserToken;
if (token.Socket != null)
{
try
{
token.Socket.Shutdown(SocketShutdown.Both);
}
catch (SocketException) { }
token.Socket.Close();
}
token.Status = 2;
bufferManager.FreeBuffer(e);
readWritePool.Push(e);
...
}
Este es un poco viejo, pero para el que lee que en el futuro: no utilice 'Environment.TickCount' para cualquier cálculo en su aplicación. Se representa como 'Int32', que se agotará en 24.9 días y se convertirá en un entero negativo y eventualmente devolverá 0. Use' DateTime.UtcNow.Ticks' en su lugar. –