c# - 未参考计时器框架 4.8 的对象未释放
问题描述
请看下面的例子。即使对 obj 的引用设置为 null,也不会释放 obj,并且 Obj_Elapsed 会继续打印 i。请注意,在 ObjectWithTimer 构造函数的范围之外没有对计时器的引用。
公共类程序{
public static void Main(string[] args)
{
object obj = new ObjectWithTimer();
Console.ReadLine();
Console.WriteLine("obj=null");
obj = null;
Console.ReadLine();
}
}
public class ObjectWithTimer
{
private int i;
public System.Timers.Timer t;
public ObjectWithTimer()
{
t = new System.Timers.Timer(5000);
t.Elapsed += Obj_Elapsed;
t.Enabled = true;
}
public void Obj_Elapsed(object sender, ElapsedEventArgs e)
{
i++;
Console.WriteLine(i);
}
}
解决方案
在这种情况下设置null
和/或超出范围是不够的,它Timer
有它正在管理的资源并且需要清理。
由于System.Timers.Timer
Implements IDisposable
,理想情况下您的包装类也应该如此
public class ObjectWithTimer : IDisposable
{
// Flag: Has Dispose already been called?
private bool _disposed = false;
private int _i;
public System.Timers.Timer Timer { get; }
public ObjectWithTimer()
{
Timer = new System.Timers.Timer(5000);
Timer.Elapsed += Obj_Elapsed;
Timer.Enabled = true;
}
public void Obj_Elapsed(object sender, ElapsedEventArgs e)
{
_i++;
Console.WriteLine(_i);
}
// Public implementation of Dispose pattern callable by consumers.
public void Dispose() =>Dispose(true);
// Protected implementation of Dispose pattern.
protected virtual void Dispose(bool disposing)
{
if (_disposed) return;
if (disposing) Timer?.Dispose();
_disposed = true;
}
}
然后,您还应该处理在某个阶段调用的包装器,而不仅仅是将其设置为null,最简单的方法是使用 using 语句
提供一种方便的语法,确保正确使用 IDisposable 对象。
public static void Main(string[] args)
{
using(object obj = new ObjectWithTimer())
{
Console.ReadLine();
Console.WriteLine("obj=null");
}
Console.ReadLine();
}
您实现一个 Dispose 方法来释放应用程序使用的非托管资源。.NET 垃圾收集器不分配或释放非托管内存。
注意:这不是关于该IDisposable
模式的完整教程,只是一个示例。请对此实施进行自己的研究和尽职调查
额外资源
推荐阅读
- r - r summary_if 有多个条件
- amazon-web-services - Amazon Redshift 的最佳集群配置
- java - 如何在 Java REST API 中处理扩展的 ascii 字符
- asp.net - ASP.Net Core 3.1 脚手架的身份页面并未全部使用(即登录页面正常,注册页面不正常)......为什么?
- javascript - 使用 jQuery 和 AJAX 时页面未加载
- django - 优化 urls.py 的路径约定
- azure - 从 Cosmos DB 集合中批量删除项目(文档)
- python - numpy dot 如何用于 3-D 矩阵
- c# - 为什么我使用 directory.delete 时 gif 文件不会删除?
- java - 如何从 Java 中的请求中仅获取一个字符串参数?