【发布时间】:2019-05-16 07:14:14
【问题描述】:
我有一个具有 System.Timers.Timer 属性的类。计时器将在使用构造函数创建对象时开始。
类定义:
public class Temp
{
public int ID { get; set; } = 0;
public System.Timers.Timer Timer { get; set; } = null;
public Temp(int id)
{
ID = id;
Timer = new System.Timers.Timer(5000);
Timer.Elapsed += Timer_Elapsed;
Timer.Enabled = true;
Timer.Start();
Console.Write(this.ID + "Class Constructor");
}
private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
Console.Write(this.ID + "Timer_Elapsed");
}
~Temp()
{
Console.Write(this.ID + "Class Distructor");
}
}
注意:
我没有在类中的任何地方调用 Timer.Stop() 方法或设置 Timer.Enable = false。这意味着只有当析构函数被调用时才会销毁定时器。我写了一个析构函数来知道这个类什么时候被销毁。
要求:
当我将空值或新实例分配给类实例变量时,我需要停止或销毁计时器。我不想通过将其公开并实现诸如 temp.Dispose() 或 temp.StopTimer() 等方法来处理类外部的计时器,其中计时器将停止,然后将一个新的 Temp 类实例分配给 temp 变量。
类使用代码示例:
static class Program
{
static void Main()
{
Temp temp = new Temp(1);
temp = null; // Or line not nacessary.
temp = new Temp(2);
GC.Collect();
GC.WaitForFullGCComplete();
Thread.Sleep(Timeout.Infinite);
}
}
我目前的理解或假设计时器何时会被销毁:
1.程序退出时:
完美运行。 析构函数被调用了两次而不是一次。 不确定这是否正常?
2。将 null 分配给变量:
我假设当分配空值或分配新实例时,旧实例有资格进行垃圾回收。所以我期待调用析构函数。但它没有被调用。 在调用析构函数或空赋值不会调用垃圾收集器时是否有时间或内存限制?
3.在c#中我们不能显式调用析构函数。
4.显式调用垃圾回收不起作用。
还有其他方法吗?
【问题讨论】:
-
您应该实现 IDisposable,而不是使用该析构函数。然后确保在完成对象后调用它。
-
这篇文章可能对您有所帮助:Juval Lowy oreilly.com/library/view/programming-net-components/0596102070/…的确定性最终确定
-
Implemented IDisposable from this link docs.microsoft.com/en-us/dotnet/standard/garbage-collection/… 所以,因为 Timer 是一种非托管类型,我们需要实现 IDIsposable 并调用像 temp.Dispose() 这样的 Dispose 方法并处理 Timer在 Dispose 方法中调用 Timer.Dispose() 和 !!我必须手动销毁定时器!!。而且仍然没有调用析构函数,对此的任何解释都会有所帮助
-
.Net 无法满足您的要求。分配新值时不能隐式调用析构函数。您正在创建的是内存泄漏,并希望框架代表您处理它。析构函数(它实际上是一个终结器)不会那样做。这是做不到的。你需要使用并调用dispose。
-
没有调用终结器,因为您在对象内部有一个循环引用。为其分配一个新值会孤立旧值,但框架不会调用终结器,因为仍然存在活动引用。它只在程序退出时调用它(是的,它可能会多次调用它,这就是为什么你有一个弃置标志),因为它在进程关闭时清理所有引用。这是内存泄漏。