2012-04-28 44 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不會在通話結束後保留​​對象,只能在之前。

爲了防止收集對象,您需要保留對它的引用。這可以通過將它存儲在類的字段中來實現(只要類實例本身不超出範圍)。