在调用Shutdown然后在Socket上关闭时获取Object Disposed异常

时间:2009-03-07 20:45:12

标签: c# networking sockets

我有一个SocketState对象,我用它将缓冲区和套接字包装在一起并传递它以与Begin / End异步套接字方法一起使用。在析构函数中,我有这个:

~SocketState()
{
    if (!_socket.Connected) return;

    _socket.Shutdown(SocketShutdown.Both);
    _socket.Close();
}

当它到达Close()时,我得到一个ObjectDisposed异常。如果我注释掉调用Shutdown(),当它到达Close()方法时我没有得到错误。我做错了什么?

编辑:

我知道IDisposable解决方案似乎是我的代码应该如何布局,但这实际上并没有解决我的问题。它不像析构函数被调用两次,那么为什么调用dispose()而不是使用析构函数来帮助我呢?在连续调用这两个函数时,我仍然会遇到相同的异常。

我查看了类似服务器的源代码,他们所做的就是将这两个语句包装在try块中并吞下异常。我会这样做,因为它似乎无害(我们无论如何都要关闭它),但我想尽可能避免它。

3 个答案:

答案 0 :(得分:3)

使用反射器;似乎Close()基本上只调用Socket上的Dispose()(它在任何一方都做了一些记录)。查看Shutdown()它在套接字句柄上调用ws2_32.dll!shutdown(),{em>也调用Dispose()。可能发生的是它试图在同一个套接字句柄上调用ws2_32.dll!shutdown()两次。

简而言之,就是致电Close()

答案 1 :(得分:2)

_socket实现了IDisposable,当你的终结器运行时,套接字已经被处理掉(或者已经完成了)。

您应该在班级上实施IDisposable并遵循处理模式。

示例:

public class SocketState : IDisposable
{
  Socket _socket;

  public SocketState()
  {
    _socket = new Socket();
  }

  public bool IsDisposed { get; private set; }

  public void SomeMethod()
  {
    if (IsDisposed)
      throw new ObjectDisposedException("SocketState");

    // Some other code
  }

  #region IDisposable Members

  public void Dispose()
  {
    Dispose(true);
    GC.SuppressFinalize(this);
  }

  protected virtual void Dispose(bool disposing)
  {
    if (!IsDisposed)
    {
      if (disposing)
      {
        if (_socket != null)
        {
          _socket.Close();
        }
      }

      // disposed unmanaged resources

      IsDisposed = true;
    }
  }

  ~SocketState()
  {
    Dispose(false);
  }

  #endregion
}

答案 2 :(得分:0)

你的问题有点不清楚。你说,那时

  

它到达Close(),你得到ObjectDisposedException

但是看,Close不会抛出任何东西。这是投放ObjectDisposedException的{​​{3}}。这可能就是为什么评论Shutdown会有所帮助 - 这正是你获得例外的原因。

我的解释是,在主对象最终确定之前,套接字会自动获取.Dispose()'(通过它自己的终结器)。

据说Shutdown

  

终结器的执行顺序是非确定性的 - 换句话说,你不能依赖终结器中仍然可用的另一个对象。