Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 自动处理线程。计时器_C#_Timer_Lambda_Dispose - Fatal编程技术网

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.@ByteBlast
null
parameter@ByteBlast,我试过了,但失败了,你能告诉我怎么做吗?该死的,我好像是个Java程序员。@MarcelN。没有人想有这种感觉。看看原始的评论。我提出了类似的建议,但正如其他人所指出的,当您尝试以其他方式处理计时器时,将出现
NullReferenceException
。@ByteBlast不使用状态参数(因为您的做法是正确的-不起作用)。使用捕获的变量
timer
@ByteBlast:usr意味着直接在lambda主体中使用timer变量,因为它可以在那里访问。我不知道你是不是这个意思。我不确定文件中的那句话今天是否准确。我相信计时器本身有一个GC句柄来保持它的活动。如果@HansPassant在附近,他肯定可以发表评论,因为他很了解计时器。@usr:它确实通过一个内部TimerQueue类保留对自身的引用,该类实际上完成了终结。将更好地调查和更新(如果Hans在此期间不发表评论)。