2011-01-20 64 views
3

我有一個Windows Service類(從ServiceBase繼承),它在構造時提供了一個對象列表。每個操作描述一個DoWork()虛擬方法。
服務類的要點是管理所有底層操作,在運行時將它們添加到列表中或將它們移除到列表中,並在ThreadPool線程中執行它們的DoWork()方法。
每個操作都有一個System.Timers.Timer對象,它被實例化並與Operation類一起運行。每個操作暴露了一個事件,以向管理類發出自己的計時器已啓動並且必須在線程中激發自己的DoWork()方法的信號。具有定時器控制的線程池操作的C#WinService

的TimedService類結合各經過定時器事件,從池中請求線程的方法:

private void CheckOperationsList(object source, EventArgs e) 
{ 
try 
    { 
    foreach (Operation op in this._operationsList) 
    { 
     lock (this._operationsList) 
     { 
     op.TimerElapsed += new Operation.ElapsedEventHandler(this.RequestThreadFromPool); 
     } 
    } 
    } 
    catch (Exception ex) { this._ManEV.WriteError(this._serviceName, ex.Message); } 
} 

當然,所述RequestThreadFromPool(對象發件人,EventArgs的)方法執行以下操作的事:

ThreadPool.QueueUserWorkItem(new WaitCallback(((Operation)sender).DoWork), new object()); 

我從進程中收到奇怪的行爲。我試圖實現與設置爲10秒的計時器,它只是保持佔用幾秒鐘處理器的虛擬操作:

for (Int16 i = 0; i < Int16.MaxValue; i++) 
    { 
    for (short j = 0; j < short.MaxValue; j++) 
    { } 
    } 

的操作單獨運行在隊列每次(我傳遞的只是一個列表服務的一個要素)一切都很正常。該過程產生自己的線程,使CPU保持幾秒鐘,然後離開。

我實現了上面虛擬方法的輕量級版本(基本上沒有內部循環)來模擬輕量級線程。

只要我在隊列中有兩個或更多的操作(使用不同的定時器!),所有線程產生三到四次,然後一切都停止。
我根本沒有活動。在Visual Studio中,它看起來像每個操作的計時器已停止滴答滴答 - 我沒有收到任何事件調用,也沒有收到任何應付事件的委託的調用;每個操作類都有自己的定時器,並且通常通過此參考定時器。 !

我試着監視所有catch {} es,並嘗試在try {}中包裝每個DoWork()方法,但我沒有得到任何異常。

令我困惑的是,如果我運行幾個相同的操作(即兩個或三個長操作或兩個或三個短操作),一切都正常運行。看起來事件來自另一個班級,一切都會變得混亂。

我開始認爲System.Timers.Timer類是所有上述的原因 - 我曾嘗試在調用Event之前調用Stop()給計時器,但無濟於事。 我得到了每個操作的DoWork()方法的4-5次迭代,然後所有東西都被關閉了。

編輯我忘了澄清一下:我運行的每個操作都是從基本操作繼承的。即:

public class TestLongOperation : Operation 
{ 
    public TestLongOperation(double secondsInterval) : base(secondsInterval) { } 
    public override void Work(object buh) 
    { 
    for (Int16 i = 0; i < Int16.MaxValue; i++) 
    { 
     for (short j = 0; j < short.MaxValue; j++) 
     { } 
    } 
} 

}

有什麼建議?如果上述不足,我可以提供更多的代碼。 在此先感謝。

+0

你從http://quartznet.sourceforge.net/試過quartz.net嗎? Quartz.net的StatefulJob應該可以幫助你。還請檢查我的一個帖子在這裏:http://stackoverflow.com/questions/3995562/what-happens-in-quartz-net-quartz-when/4225590#4225590 – 2011-01-20 14:16:38

+0

我會看看它,但我希望通過自己做一點點學習。謝謝! – SimoneF 2011-01-20 14:38:43

回答

1

我有一種感覺計時器在每個滴答事件上創建一個新的線程,我的服務有一個問題,導致大量的線程被產生,如果大量的處理仍在繼續從上一個滴答滴答下一個滴答開始。

我最終完全刪除了定時器,並用循環替換它。然後在我的主要處理線程中添加了一個Thread.sleep。這就像一個計時器,但不會產生線程。此外,循環直到處理完成纔會結束。

如:

(主要THEAD)

bool running = true; 

while (running) 
{ 

    //do processing 


    /sleep for 'timer' interval 
    Thread.Sleep(interval) 
} 

有何幫助呢?

+0

這正是我認爲正在發生的事情。 System.Threading.Timer應該做同樣的事情。在最初的實現中,監督類有自己的計時器,所有的操作僅僅是DoWork()方法的包裝器,擁有nextRun DateTime屬性和Interval屬性;每次迭代,監督器循環遍歷隊列,運行已過期的DoWork()線程,並將Interval添加到NextRun屬性,但我希望線程本來是一個更好的實現(輪詢或運行無限,而聽起來不正確)。謝謝! – SimoneF 2011-01-20 13:53:08

0

一些隨機的想法:

當程序掛起,你打突破和cheeck如果你是一對夫婦的「鎖定」行。

這是一個定時器嗎?如果是這樣,在啓用定時器之前,請連接事件處理程序。如果不是,你的工作是否可重入?

在計時器處理程序中,爲什麼會產生另一個線程來完成這項工作?計時器已經把它放在一個新的線程中。也許你打線程池耗盡?如果多個定時器處理程序啓動並使用了線程池,那麼它們將等待啓動工作線程。

閱讀Timer.SynchronizingObject Property看到Timer可以使用ThreadPool。