构造函数中声明的C#对象的垃圾回收
在下面的代码中,我在类的构造函数中创建了一个Dispatchermer。没有人在上面保留参考资料 在我的理解中,计时器应该在离开构造函数的作用域后由垃圾收集器回收。 但那不会发生!即使在使用构造函数中声明的C#对象的垃圾回收,c#,.net,constructor,garbage-collection,C#,.net,Constructor,Garbage Collection,在下面的代码中,我在类的构造函数中创建了一个Dispatchermer。没有人在上面保留参考资料 在我的理解中,计时器应该在离开构造函数的作用域后由垃圾收集器回收。 但那不会发生!即使在使用GC.Collect() 引擎盖下发生了什么 public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); new DispatcherTimer
GC.Collect()
引擎盖下发生了什么
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
new DispatcherTimer
{
Interval = TimeSpan.FromMilliseconds(100),
IsEnabled = true
}
.Tick += (s, e) =>
{
textBlock1.Text = DateTime.Now.ToString();
};
}
}
计时器非常特殊,因为它们通过调用
this.timerRoot = GCHandle.Alloc(this);
一些链接没有意识到它是一个
调度程序
——它不是直接地,而是间接地(对调度程序
)进行根处理,这反过来会产生同样的效果…它将被添加到将被根处理的调度程序
队列中 当您仅构建aDispatchermer
时,没有什么可以阻止它被GCed。但是,您可以设置IsEnabled=true
,这将在计时器上调用Start()
。发生这种情况时,将执行以下代码行:
this._dispatcher.AddTimer(this);
现在,
调度程序
本身正在为计时器设置根,这意味着它不能被GCed。调度程序是否遵循与线程相同的垃圾收集规则。计时器?如果是这样,没有对计时器的字段引用(仅本地引用)将导致垃圾回收本身…但我认为Dispatchermers不是这样的…@JeffN825所有对象都受相同的GC规则约束:如果无法从GC根目录访问,则可以使用GC。在本例中,该代码甚至不是来自正确的timer类。@dlev只是没有意识到它是一个Dispatchermer-请参阅我的EDITMy。我的观点是一个局部范围的线程。只有一个局部引用的timer不是根线程…因此将在没有任何滴答声的情况下进行GC。@JeffN825这并不总是正确的。。。因为计时器可以直接或间接地“根自身”。。。我没有检查Threading.Timer源(通过Reflector),但它在内部调用了TimerBase.AddTimer,这似乎创建了一个引用,即使对于本地范围的计时器也是如此。。。所以它也很可能“间接地植根于”你的场景中。。。