2012-04-28 43 views
1

我在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

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

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

+0

你有什么建议可以永生吗?我也有我的课保持活力,这足够吗? – user1054776 2012-04-28 03:33:13

+0

@ user1054776,我已经更新了我的答案,使其更加清晰。 – Matt 2012-04-28 03:38:43

+0

哇,这是工作...非常感谢你 – user1054776 2012-04-28 04:03:06

1

根据对KeepAlive的文档:

这种方法引用obj参数,使该对象没有资格获得该过程移至点开始垃圾收集,在执行顺序,在这种方法被称为。在obj必须可用的指令范围的最后而非开始处编码此方法。

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

换句话说,KeepAlive干脆什么也不做,但引用变量,使的KeepAlive调用之前,GC将无法收集。这对局部变量是有用的,这些局部变量需要坚持到超出范围。下面是一个简单的例子:

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

没有KeepAlive,该方法可以被优化,以在定时器经过长时间运行的操作中途收集的点。

简单的说,KeepAlive不会在通话结束后保留​​对象,只能在之前。

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