c# - 特定情况下的 C# Dispose() 标准
问题描述
我们知道 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();
}
}
解决方案
你显然在滥用一次性模式。
Dispose(bool disposing)
意味着当不再需要对象并且永远不会再次使用时,只调用一次。这可能是因为有人直接调用Dispose()
(调用Dispose(true)
),也可能是因为对象的终结器运行(调用Dispose(false)
)。此外,正如@Dmytro Mukalov 指出的那样,在此期间使用托管对象Dispose(false)
是不安全的,并且可能导致难以调试的问题(但仅当您的对象实际上具有终结器时才适用)。
如果您正在尝试实现对象池,我建议您创建然后将池服务注入到 thisTCPStream
中。它将管理池对象的生命周期并允许Rent
和Return
操作。然后TCPStream.Dispose()
将Return
任何先前Rent
编辑的对象并摆脱其自己的资源,而实际的池化对象将仅在池化服务被释放时才会被释放(您可以将其设置为在TCPServer
关闭时)。就目前而言,您的TCPStream
职责太多,这会阻止您正确实施一次性模式。
推荐阅读
- python - functools reduce In-Place 修改原始数据框
- reactjs - 如何在 react.js 页面中使用 cordova 插件
- json - 由于额外的反斜杠,在 Elm 中解码 Dict 失败
- c# - 悬停时如何更改线的颜色,包括另一条线的所有最近点
- python - 查看 LabelEncoder 的映射
- visual-studio-code - 有没有办法在不同的显示器上更改缩放级别和字体大小?
- javascript - jQuery KeyUp 和鼠标点击不能工作相同的功能
- android - Android:如何测试 android 车速表
- android - Android 调试如何在幕后工作?
- javascript - 正则表达式:如果表达式存在则匹配,但如果表达式之前有特定字符串不匹配