C# .net异步套接字超时检查线程安全
从上面的msdn示例开始,我尝试编写一个超时检查,它将关闭不活动的客户端套接字并释放资源 这就是我想到的。但我不确定它是否完全线程安全,是否有更好的方法来实现这一点。我希望有人能给我一些建议C# .net异步套接字超时检查线程安全,c#,multithreading,asynchronous,sockets,timeout,C#,Multithreading,Asynchronous,Sockets,Timeout,从上面的msdn示例开始,我尝试编写一个超时检查,它将关闭不活动的客户端套接字并释放资源 这就是我想到的。但我不确定它是否完全线程安全,是否有更好的方法来实现这一点。我希望有人能给我一些建议 void IO_Completed(object sender, SocketAsyncEventArgs e) { if (e.SocketError != SocketError.Success) { CloseClientSocket(e); retur
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);
}
void IO_已完成(对象发送方,SocketAsyncEventArgs e)
{
如果(例如SocketError!=SocketError.Success)
{
闭合客户端插座(e);
返回;
}
if(1<联锁比较交换(参考标记状态,1,0))
返回;
开关(如上次操作)
{
案例SocketAsyncOperation。接收:
处理接收(e);
打破
...
}
token.LastActive=Environment.TickCount;
联锁比较交换(参考标记状态,0,1);
}
void ProcessReceive(SocketAsyncEventArgs e)
{
AsyncUserToken=(AsyncUserToken)e.UserToken;
如果(例如,ByTestTransferred>0)
if(!token.Socket.SendAsync(e))
ProcessSend(e);
其他的
闭合客户端插座(e);
}
void ProcessSend(SocketAsyncEventArgs e)
{
AsyncUserToken=(AsyncUserToken)e.UserToken;
if(!token.Socket.ReceiveAsync(e))
处理接收(e);
}
超时检查将每20秒执行一次。allReadWriteArgs是一个包含所有SocketAsyncEventArgs的数组。关闭套接字后,将使用SocketError.OperationAborted调用IO_Completed
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);
...
}
void TimeoutCheck(对象状态)
{
异步用户令牌;
int timeout=Environment.TickCount-20000;
for(int i=0;i
您的代码看起来不错。您也可以这样做:
void _connectionActivityCheck_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
_connectionActivityCheck.Stop();
try
{
List<Guid> connectionsToRemove = new List<Guid>();
lock (_connections.SyncRoot)
{
IncomingConnection conn;
foreach (DictionaryEntry item in _connections)
{
conn = (IncomingConnection)item.Value;
if (conn.LastIncomingActivity.HasValue &&
DateTime.Now.Subtract(conn.LastIncomingActivity.Value).TotalSeconds > MaximumInactivitySeconds)
connectionsToRemove.Add(conn.ConnectionId);
}
}
if (connectionsToRemove.Count > 0)
{
int itemsToRemove = connectionsToRemove.Count;
foreach (Guid item in connectionsToRemove)
{
RemoveConnection(item);
}
Context.Current.Logger.LogInfo(_loggerName,
string.Format("{0} connections were closed due to incoming traffic inactivity", itemsToRemove));
}
}
catch (Exception ex)
{
Context.Current.Logger.LogFatal(_loggerName, "An error ocurred while checking incoming traffic.", ex);
}
finally
{
_connectionActivityCheck.Start();
}
}
private void RemoveConnection(Guid connectionId)
{
lock (_connections.SyncRoot)
{
try
{
IncomingConnection conn = _connections[connectionId] as IncomingConnection;
if (conn != null)
{
try
{
conn.Dispose();
}
catch { }
_connections.Remove(connectionId);
}
}
catch { }
}
}
void\u connectionActivityCheck\u过期(对象发送方,System.Timers.ElapsedEventArgs e)
{
_connectionActivityCheck.Stop();
尝试
{
列表连接存储移动=新建列表();
锁定(_connections.SyncRoot)
{
进线连接接头;
foreach(DictionaryEntry项在_connections中)
{
conn=(IncomingConnection)项值;
if(conn.LastIncomingActivity.HasValue&&
DateTime.Now.Subtract(conn.LastIncomingActivity.Value).TotalSeconds>MaximumActivitySeconds)
connectionsToRemove.Add(conn.ConnectionId);
}
}
如果(ConnectionsStoreMove.Count>0)
{
int itemsToRemove=connectionsToRemove.Count;
foreach(connectionsToRemove中的Guid项)
{
移除连接(项目);
}
Context.Current.Logger.LogInfo(_loggerName,
Format(“{0}连接因传入流量不活动而关闭”,itemsToRemove));
}
}
捕获(例外情况除外)
{
Context.Current.Logger.LogFatal(_loggerName,“检查传入流量时发生错误”,例如);
}
最后
{
_connectionActivityCheck.Start();
}
}
私有void RemoveConnection(Guid connectionId)
{
锁定(_connections.SyncRoot)
{
尝试
{
IncomingConnection conn=_connections[connectionId]作为IncomingConnection;
如果(conn!=null)
{
尝试
{
conn.Dispose();
}
捕获{}
_连接。移除(connectionId);
}
}
捕获{}
}
}
这有点老了,但对于将来阅读这篇文章的人来说:不要在应用程序中的任何计算中使用Environment.TickCount
。它表示为Int32
,将在24.9天内运行,并循环到一个负整数,最终返回0。改用DateTime.UtcNow.Ticks
。