我在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次,之后我的计时器不再执行了。我需要它保持直到服务停止
任何人都知道为什么我的计时器会一直停止滴答?
答案 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
不会在通话之后保留对象,只是在此之前。
要防止收集对象,您需要保留对它的引用。这可以通过将其存储在类的字段中来实现(只要类实例本身不超出范围)。