In the following code, I create a DispatcherTimer in the class's constructor. No one keeps reference on it.
在下面的代码中,我在类的构造函数中创建了一个DispatcherTimer。没有人对它保持引用。
In my understanding, the timer should be reclaimed by the garbage collector some time after leaving the constructor's scope. But that doesn't happen! Even after forcing a garbage collection with GC.Collect()
在我的理解中,计时器应该在离开构造函数的范围后的一段时间内由垃圾收集器回收。但这并不发生!即使在使用GC.Collect()强制执行垃圾收集之后
What is going on under the hood?
引擎盖下面发生了什么事?
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
new DispatcherTimer
{
Interval = TimeSpan.FromMilliseconds(100),
IsEnabled = true
}
.Tick += (s, e) =>
{
textBlock1.Text = DateTime.Now.ToString();
};
}
}
3 个解决方案
#1
3
When you just construct the a DispatcherTimer
, nothing prevents it from be GCed. However, you set IsEnabled = true
, which will call Start()
on the timer. When that, happens, this line of code will be executed:
当您只是构造一个DispatcherTimer时,没有什么可以阻止它被GCed。但是,您设置了IsEnabled = true,它将在计时器上调用Start()。当这种情况发生时,这一行代码将被执行:
this._dispatcher.AddTimer(this);
And now the Dispatcher
itself is rooting the timer, meaning it can't be GCed.
现在调度程序本身正在启动计时器,这意味着它不能被GCed。
#2
4
Timers are rather special since they root themselves by calling
计时器是相当特殊的,因为它们通过调用来建立自己的根
this.timerRoot = GCHandle.Alloc(this);
some links
一些链接
- Timer, event and garbage collection : am I missing something?
- 计时器、事件和垃圾收集:我是否遗漏了什么?
- Event handler and memory leaks
- 事件处理程序和内存泄漏
- http://blogs.msdn.com/b/abhinaba/archive/2009/05/05/memory-leak-via-event-handlers.aspx
- http://blogs.msdn.com/b/abhinaba/archive/2009/05/05/memory-leak-via-event-handlers.aspx
EDIT:
编辑:
Didn't realize that it was a DispatcherTimer
- that doesn't root itself directly but indirectly (to the Dispatcher
) which in turn leads to the same effect...
没有意识到这是一个DispatcherTimer——它不会直接地根起自己,而是间接地根起(对Dispatcher),反过来导致相同的效果……
#3
1
It will be added to the Dispatcher
queue which will be rooted.
它将被添加到将被根化的Dispatcher队列中。
#1
3
When you just construct the a DispatcherTimer
, nothing prevents it from be GCed. However, you set IsEnabled = true
, which will call Start()
on the timer. When that, happens, this line of code will be executed:
当您只是构造一个DispatcherTimer时,没有什么可以阻止它被GCed。但是,您设置了IsEnabled = true,它将在计时器上调用Start()。当这种情况发生时,这一行代码将被执行:
this._dispatcher.AddTimer(this);
And now the Dispatcher
itself is rooting the timer, meaning it can't be GCed.
现在调度程序本身正在启动计时器,这意味着它不能被GCed。
#2
4
Timers are rather special since they root themselves by calling
计时器是相当特殊的,因为它们通过调用来建立自己的根
this.timerRoot = GCHandle.Alloc(this);
some links
一些链接
- Timer, event and garbage collection : am I missing something?
- 计时器、事件和垃圾收集:我是否遗漏了什么?
- Event handler and memory leaks
- 事件处理程序和内存泄漏
- http://blogs.msdn.com/b/abhinaba/archive/2009/05/05/memory-leak-via-event-handlers.aspx
- http://blogs.msdn.com/b/abhinaba/archive/2009/05/05/memory-leak-via-event-handlers.aspx
EDIT:
编辑:
Didn't realize that it was a DispatcherTimer
- that doesn't root itself directly but indirectly (to the Dispatcher
) which in turn leads to the same effect...
没有意识到这是一个DispatcherTimer——它不会直接地根起自己,而是间接地根起(对Dispatcher),反过来导致相同的效果……
#3
1
It will be added to the Dispatcher
queue which will be rooted.
它将被添加到将被根化的Dispatcher队列中。