我们知道Dispose(布尔处置)应受保护或私有,如果我需要手动释放未管理的资源怎么办?接口IDISPOSIBLE的Dispose()必须调用Dispose(true),这意味着释放所有资源。我想手动控制管理和取消资源的发布。
实现Dispose的正式方法是https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-dispose。但是有时我需要使用Dispose(false)手动释放某些资源,该功能应该是公共的,还是我需要创建另一个函数如DisposeUnManage()来手动处理未管理的资源?
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing) {
handle.Dispose();
// Free any other managed objects here.
}
disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public void DisposeUnmanage()
{
Dispose(false);
}
private void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing) {
handle.Dispose();
// Free any other managed objects here.
}
disposed = true;
}
像来自TCPStream的这段代码一样,当TCP客户端断开连接时,我需要使用此TCPStream.Dispose(false)方法。当我关闭TCPServer时,我应该调用TCPStream.Dispose(true)。
/// <summary>
/// Closes the underlying socket
/// </summary>
/// <param name="disposing">
/// If true, the EventArg objects will be disposed instead of being re-added to
/// the IO pool. This should NEVER be set to true unless we are shutting down the server!
/// </param>
private void Dispose(bool disposeEventArgs = false)
{
// Set that the socket is being closed once, and properly
if (SocketClosed) return;
SocketClosed = true;
// If we need to dispose out EventArgs
if (disposeEventArgs)
{
ReadEventArgs.Dispose();
WriteEventArgs.Dispose();
DisposedEventArgs = true;
}
else
{
// Finally, release this stream so we can allow a new connection
SocketManager.Release(this);
Released = true;
}
// Do a shutdown before you close the socket
try
{
Connection.Shutdown(SocketShutdown.Both);
}
catch (Exception) { }
finally
{
// Unregister for vents
ReadEventArgs.Completed -= IOComplete;
WriteEventArgs.Completed -= IOComplete;
// Close the connection
Connection.Close();
Connection = null;
}
// Call Disconnect Event
if (!DisconnectEventCalled && OnDisconnected != null)
{
DisconnectEventCalled = true;
OnDisconnected();
}
}
您显然正在滥用一次性样式。
Dispose(bool disposing)
意味着当不再需要该对象且将不再使用时,将被精确地调用一次。可能是因为有人直接调用了Dispose()
(它调用了Dispose(true)
),也可能是因为该对象的终结器运行了(它调用了Dispose(false)
)。此外,正如@Dmytro Mukalov指出的那样,在Dispose(false)
期间使用托管对象是不安全的,并且可能导致难以调试的问题(但仅在您的对象实际具有终结器的情况下才适用)。
如果您要实现对象池,建议您创建一个池服务,然后将其插入此TCPStream
。它可以管理合并对象的生存期,并允许Rent
和Return
操作。然后,TCPStream.Dispose()
将Return
先前所有的Rent
对象释放其自身的资源,而实际的池化对象仅在池服务被处置时才被处置(可以将其设置为TCPServer
关掉)。从目前的情况来看,您的TCPStream
职责过多,无法正确实施一次性模式。