服务计时器永远活着

时间:2012-04-28 03:15:54

标签: c# garbage-collection

我在c#中构建服务应用程序。我试图每2秒用计时器做一次动作(数组)。但是我的计时器在我的函数调用结束后仍然死掉。

我的Onstart:

   ...
   Alaram  Fi = new Alaram();
   Fi.AgentStart();
   GC.KeepAlive(Fi);
   ...

我的Alaram课程:

    public void AgentStart()
    {
        ...
        int i = 0;
        Timer[] timers = new Timer[count];

        while (myReader.Read())
        {
            timers[i] = new Timer(coba, myReader["DeviceId"], 0, 2000);
            i++;
        }
        GC.KeepAlive(timers);

     }

我的行动:

 public void coba(object id)
 {
        ...

        int sec = Convert.ToInt32((string)myCommand.ExecuteScalar());
        sec++;

        myCommand = new SqlCommand("UPDATE Roles  SET  Value ='" + sec.ToString() + "' WHERE   Name = 'Fire" + id.ToString() + "'", ibmsConnect);
        myCommand.ExecuteNonQuery();
        ...
  }

我的计时器只执行了最多36次,之后我的计时器不再执行了。我需要它保持直到服务停止

任何人都知道为什么我的计时器会一直停止滴答?

2 个答案:

答案 0 :(得分:3)

GC.KeepAlive只会阻止对它们被声明(或存储)的作用域的定时器进行积极的垃圾收集,这将是AgentStart方法中的数组。一旦数组和定时器超出范围(当方法执行完毕时),它们将开始通过垃圾收集来收集。

您需要在一个位于其范围内的位置声明该数组。一种方法是将数组标记为静态并将其放在类级别上。接下来,在类的静态构造函数中实例化分配给数组的计时器。这应该让他们活着。

答案 1 :(得分:2)

根据KeepAlive的文档:

  

此方法引用obj参数,使该对象不具有从例程开始到执行顺序的点的垃圾收集的资格,此处调用此方法。在obj必须可用的指令范围的末尾而不是开头编码此方法。

     

KeepAlive方法不执行任何操作,除了延长作为参数传入的对象的生命周期外,不会产生任何副作用。

换句话说,KeepAlive根本不执行任何操作,但会引用该变量,以便GC在<{em> KeepAlive调用之前不会收集它。这对于需要在超出范围之前需要保留的局部变量非常有用。这是一个简单的例子:

void DoSomething()
{
    Timer myTimer = ...;
    // long-running operation
    GC.KeepAlive(myTimer);
}

如果没有KeepAlive,该方法可以优化到在长时间运行操作的中途收集Timer的位置。

简单地说,KeepAlive不会在通话之后保留对象,只是在此之前。

要防止收集对象,您需要保留对它的引用。这可以通过将其存储在类的字段中来实现(只要类实例本身不超出范围)。