title: .net async socket timeout check thread-safety
body: <p><a href="http://msdn.microsoft.com/en-us/library/system.net.sockets.socketasynceventargs.aspx" rel="noreferrer">http://msdn.microsoft.com/en-us/library/system.net.sockets.socketasynceventargs.aspx</a></p>
  
  <p>Starting with the above msdn example I'm trying to write a timeout check which will close inactive client sockets and free up resources.</p>
  
  <p>This is what I have come up with. But I'm not sure if its completely thread-safe and if there is a better way to do this. I hope someone can give some advices.</p>
  
  <pre><code>void IO_Completed(object sender, SocketAsyncEventArgs e)
  {
      if (e.SocketError != SocketError.Success)
      {
          CloseClientSocket(e);
          return;
      }
  
      if (1 &lt; 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 &gt; 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);
  }
  </code></pre>
  
  <p>TimeoutCheck will execute once each 20 seconds. allReadWriteArgs is an array with all  SocketAsyncEventArgs. After closing the socket IO_Completed will be invoked with SocketError.OperationAborted.</p>
  
  <pre><code>void TimeoutCheck(object state)
  {
      AsyncUserToken token;
      int timeout = Environment.TickCount - 20000;
      for (int i = 0; i &lt; allReadWriteArgs.Length; i++)
      {
          token = (AsyncUserToken)allReadWriteArgs[i].UserToken;
          if (token.LastActive &lt; 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);
      ...
  }
  </code></pre>