1

我在 C# 中构建了一个服务应用程序。我正在尝试每 2 秒使用计时器进行一次操作(数组)。但是在我的函数调用完成后,我的计时器继续消失。

我的开始:

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

我的警报类:

    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 次。我需要它保持活动状态,直到服务停止

有人知道为什么我的计时器不停地滴答作响吗?

4

2 回答 2

3

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

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

于 2012-04-28T03:30:09.103 回答
2

根据以下文档KeepAlive

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

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

换句话说,KeepAlive只是什么都不做,只是引用变量,这样 GC 就不会在调用之前收集它。KeepAlive这对于需要保留直到超出范围的局部变量很有用。这是一个简单的例子:

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

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

简单地说,KeepAlive在调用之后不保留对象,只保留之前。

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

于 2012-04-28T04:32:25.627 回答