未命名的计时器线程不会执行

时间:2011-03-28 19:54:13

标签: c# multithreading

想知道是否有人可以回答让我困扰的事情。

我有一个Timer,它设置一个变量让其他一些线程知道何时停止执行(这个例子的长度是硬编码的)

Timer endProcessingThread = new Timer(x => _endOfProcessingTimeHasElapsed = true, null, 10000, 0);

我从来没有加入线程或使用计时器变量名称来做任何事情,所以我'清理'它说:

new Timer(x => _endOfProcessingTimeHasElapsed = true, null, 10000, 0);

这个编译很好但线程永远不会执行。

任何人都知道为什么?

4 个答案:

答案 0 :(得分:4)

我的猜测是,在10秒钟之前,Timer已超出范围并被GCed。来自MSDN:

  

只要您使用Timer,就必须保留对它的引用。与任何托管对象一样,当没有对它的引用时,Timer会进行垃圾回收。定时器仍处于活动状态这一事实并不能阻止它被收集。

解决方案是通过将引用分配给某个类或表单属性/字段,在10秒内(或每当)保持该引用的任何代码级别。

答案 1 :(得分:2)

  

这个编译很好但线程永远不会执行。

垃圾收集器可能会在触发之前清除匿名计时器。

请参阅此SO question

答案 2 :(得分:2)

首先:TimerIDisposable,因此使用计时器的变量名称,至少要正确处理它。

并且:由于您没有保留对创建的实例的任何引用,因此它有资格进行垃圾回收。由于Timer的内部使用终结器,因此调用终结器并在有机会触发之前删除定时器。 (请注意,只有在第一种情况下保留在命名局部变量中的引用是不够的,编译器可能会注意到该变量根本没有被使用并且无论如何都会垃圾收集该实例。)

解决方案:保留引用并在完成使用后立即致电Dispose()

答案 3 :(得分:1)

可能因为你永远不会持有对你创建的对象的引用,它会立即被优化掉(没有左值),或者它只是得到GC并且永远不会执行。

FWIW不是那个类实现IDisposable吗?如果是这样,您应该使用using语句或调用dispose。