.net сокеты ObjectDisposed исключение - PullRequest
0 голосов
/ 19 апреля 2011

Я использую асинхронные сокеты в моем проекте.

При вызове метода Disconnect в моем классе возникает исключение NotifyConnection ObjecDispoded. Я понимаю, что это происходит потому, что метод socket.Close () вызывает метод Dispose внутри.

Кто-нибудь знает, как закрыть сокет в этой ситуации?

    public void Disconnect()
    {
        try
        {
            lock (_syncRoot)
            {                    
                _clientSocket.Shutdown(SocketShutdown.Both);
                _clientSocket.Close();
            }
        }
        catch (SocketException ex)
        {
            OnSocketExeceptionThrowed(new EventArgs<SocketException>(ex));
            NotificationAgentEm.LogExceptionToConsole(ex);
        }

    }

Я объясняю, что EndReceive не вызывается, потому что socket.ShutDown закрывает данные, принимаемые сокетом ... но EndReceive вызывается после socket.ShutDown; socket.Close.

Завершено исключение, так как сокет не существует в данный момент.

   private void OnReceiveData(IAsyncResult ar)
    {
        try
        {
            TransferStateObject state = null;
            lock(_syncRoot)
            {
                string message;
                state = (TransferStateObject)ar.AsyncState;
                // in this place exception throwed . client socket not exist becaouse it destroyed in disconnect method
                int bytesRead = _clientSocket.EndReceive(ar);

keleton о том, как я использую асинхронные сокеты.

   public void Connect(string host, int port)
    {
        if (host == null)
            throw new NullReferenceException();            
        try
        {
            _clientSocket = new Socket(AddressFamily.InterNetwork,
                                   SocketType.Stream, ProtocolType.Tcp);
            _clientSocket.Connect(host, port);
        }
        catch (Exception ex)
        {
            NotificationAgentEm.LogExceptionToConsole(ex);
            throw;
        }
    }
   public void Disconnect()
    {
        try
        {
            lock (_syncRoot)
            {                    
                _clientSocket.Shutdown(SocketShutdown.Both);
                _clientSocket.Close();
            }
        }
        catch (SocketException ex)
        {
            OnSocketExeceptionThrowed(new EventArgs<SocketException>(ex));
            NotificationAgentEm.LogExceptionToConsole(ex);
        }

    }
       public void StartListen()
    {
        if (_clientSocket == null)
        {
            throw new InvalidOperationException("No connection");
        }
        try
        {
            BeginReceive();
        }
        catch (SocketException ex)
        {              
            NotificationAgentEm.LogExceptionToConsole(ex);
            OnSocketExeceptionThrowed(new EventArgs<SocketException>(ex));
        }
    }  

  private void BeginReceive()
    {
        try
        {
            var receivedTranferObject = new TransferStateObject();
            _clientSocket.BeginReceive(
                receivedTranferObject.Buffer,
                0,
                TransferStateObject.BufferSize,
                0,
                new AsyncCallback(OnReceiveData),
                receivedTranferObject);
        }
        catch(SocketException ex)
        {
            OnSocketExeceptionThrowed(new EventArgs<SocketException>(ex));
            NotificationAgentEm.LogExceptionToConsole(ex);
        }
    }
  private void OnReceiveData(IAsyncResult ar)
    {
        try
        {
            TransferStateObject state = null;
            lock(_syncRoot)
            {
                string message;
                state = (TransferStateObject)ar.AsyncState;
                // in this place exception throwed . client socket not exist becaouse it    destroyed in disconnect method
                int bytesRead = _clientSocket.EndReceive(ar);
                 //bla bla bla
             }
         }

p.s извините за мой английский

1 Ответ

1 голос
/ 19 апреля 2011

Независимо от моего комментария выше, я бы реструктурировал метод Disconnect:

try
{
  lock (_syncRoot)
  {                    
      if ( null != _clientSocket )
      {
           _clientSocket.Shutdown(SocketShutdown.Both);
           _clientSocket.Close();
           _clientSocket = null;
       }
   }
}
catch (SocketException ex)
...

Таким образом, вы не выключаете / не закрываете сокет второй раз.

Но опять же, чтобы действительно помочь вам, нам нужно больше подробностей об основном рабочем процессе.

НТН

PS: я знаю о наказании за то, что если внутри замка, но я хотел, чтобы это было просто,

Mario

РЕДАКТИРОВАТЬ: я добавил функцию после обсуждения в разделе комментариев:

private void OnReceiveData(IAsyncResult ar)
{
  if ( null != _clientSocket )
  { 
     try
      {
        TransferStateObject state = null;
        lock(_syncRoot)
        {
          string message;
          state = (TransferStateObject)ar.AsyncState;
          int bytesRead = _clientSocket.EndReceive(ar);
          //bla bla bla
        }
      }
   }
  else
  {
    //socket has been closed/ is closing
   }
}

НТН

Mario

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...