C# 自动处理线程。计时器
我想要一些非常简单的东西C# 自动处理线程。计时器,c#,timer,lambda,dispose,C#,Timer,Lambda,Dispose,我想要一些非常简单的东西 // increment counter Interlocked.Increment(ref _counter); // automatically decrement counter after 1 sec Timer timer = new Timer((o) => { Interlocked.Decrement(ref _counter); (o as Timer).Dispose(); }, timer, 1000, Timeout.In
// increment counter
Interlocked.Increment(ref _counter);
// automatically decrement counter after 1 sec
Timer timer = new Timer((o) => {
Interlocked.Decrement(ref _counter);
(o as Timer).Dispose();
}, timer, 1000, Timeout.Infinite);
但是,此代码不可编译
使用未分配的局部变量“timer”
有什么简单的方法可以解决吗?它必须是Threading.Timer
注意:我不确定我是否必须调用Dispose
,它显然是未管理的资源,并且它是IDisposable
,仍然处于警告状态
只要使用计时器,就必须保留对它的引用。与任何托管对象一样,当没有对计时器的引用时,计时器将接受垃圾收集。计时器仍处于活动状态这一事实并不妨碍对其进行收集
我真的希望它被收集(自动处理?)。那么,是处置还是不处置?如果不保留对它的引用,自我处置将不起作用。即使不是定期的,你也有被垃圾收集的风险。因此,它可能在第一次滴答声之前就被垃圾收集了 从文件中: 只要使用计时器,就必须保留对它的引用。作为 对于任何托管对象,计时器在 没有提到它。计时器仍处于活动状态的事实 不会阻止它被收集
另一方面,即使您不处理它,它也会通过它的终结器发布(尽管依赖它不是一个好的实践)。这可以在计时器的源代码中看到。有一种模式:
Timer timer = null;
timer = new Timer...
现在可以在lambda主体中使用计时器
。这基本上是一种让编译器在做同样的事情时感到高兴的方法
一定要扔掉那个计时器。计时器可能由操作系统句柄资源进行备份(我相信CLR实现更改了几次)。我相信计时器还包含一个GC句柄。这是无害的,大部分时间不处理。但谁知道大量未经处理的计时器会导致什么罕见的资源枯竭呢
做一点代码检查:如果您希望强制转换始终有效,请不要使用
as
,因为as
说明了失败是一种预期情况。不:(o作为计时器)
。取而代之的是:((Timer)o)
如果您处理垃圾很重要,您应该尝试以下方法:
class Foo {
private Timer _timer;
...
public void IncrementForASecond()
{
Interlocked.Increment(ref _counter);
if(_timer != null)
_timer.Dispose();
_timer = new Timer((o) => {
Interlocked.Decrement(ref _counter);
}, null, 1000, Timeout.Infinite);
}
通过这种方式,您可以确保始终有一个计时器的引用,并且在创建新计时器之前,您正在处理上一个计时器。您真的需要
系统中的计时器。
。使用System.Timers.Timer
可以更轻松地完成此操作。此外,我认为您很清楚为什么会出现错误。您可以通过分离声明和赋值来解决编译时错误。@MarcelN.,是的。这是仍将传递给state的catch.@ByteBlastnull
parameter@ByteBlast,我试过了,但失败了,你能告诉我怎么做吗?该死的,我好像是个Java程序员。@MarcelN。没有人想有这种感觉。看看原始的评论。我提出了类似的建议,但正如其他人所指出的,当您尝试以其他方式处理计时器时,将出现NullReferenceException
。@ByteBlast不使用状态参数(因为您的做法是正确的-不起作用)。使用捕获的变量timer
@ByteBlast:usr意味着直接在lambda主体中使用timer变量,因为它可以在那里访问。我不知道你是不是这个意思。我不确定文件中的那句话今天是否准确。我相信计时器本身有一个GC句柄来保持它的活动。如果@HansPassant在附近,他肯定可以发表评论,因为他很了解计时器。@usr:它确实通过一个内部TimerQueue类保留对自身的引用,该类实际上完成了终结。将更好地调查和更新(如果Hans在此期间不发表评论)。