我有一个SocketState对象,我用它将缓冲区和套接字包装在一起并传递它以与Begin / End异步套接字方法一起使用。在析构函数中,我有这个:
~SocketState()
{
if (!_socket.Connected) return;
_socket.Shutdown(SocketShutdown.Both);
_socket.Close();
}
当它到达Close()时,我得到一个ObjectDisposed异常。如果我注释掉调用Shutdown(),当它到达Close()方法时我没有得到错误。我做错了什么?
我知道IDisposable解决方案似乎是我的代码应该如何布局,但这实际上并没有解决我的问题。它不像析构函数被调用两次,那么为什么调用dispose()而不是使用析构函数来帮助我呢?在连续调用这两个函数时,我仍然会遇到相同的异常。
我查看了类似服务器的源代码,他们所做的就是将这两个语句包装在try块中并吞下异常。我会这样做,因为它似乎无害(我们无论如何都要关闭它),但我想尽可能避免它。
答案 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)