【发布时间】:2020-02-03 19:15:50
【问题描述】:
我们知道 Dispose(bool disposing) 应该是受保护的或私有的,如果我需要手动释放未管理的资源怎么办?来自接口 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();
}
}
【问题讨论】:
-
仅为非托管资源创建或使用
IDisposable类型,并将其传递给构造函数(依赖注入器)。然后调用者可以处理它并......等等,如果调用者控制非托管资源的处理,那不会让你的类型处于不稳定状态吗?我闻到了XY problem,你真正需要解决的是什么? -
"有时我需要使用 Dispose(false) 手动释放某些资源" -- 这是什么意思?将
false传递给Dispose(bool)用于终结器,即释放仅 非托管资源,因为运行时将负责处理可终结对象。你不应该在其他时间调用它。我怀疑是否需要能够处理您拥有的对象的某些子集,但如果必须,只需为客户端代码调用一个完全独立的公共方法。不过也许你应该写一个缓存。 -
一次性类背后的想法是它包装/隐藏调用者的资源。调用者只需要在完成后调用 Dispose。它不应该像这样直接管理它。
-
如果您需要释放某些资源并留下其他资源,则可能表明存在严重的设计缺陷,尤其是职责分解问题。顺便说一句,您的
Dispose方法非常不安全 - 无论如何调用它,它都使用托管对象,并且从终结器触发可能会导致严重问题。
标签: c# dispose idisposable