我想每10秒鐘從Windows服務(使用C#和.NET完成)調用業務層方法。但是,我不想使用Timer_Elapsed事件,因爲它啓動另一個線程/進程,如果第一個線程/進程仍在運行。我只需要一種單線程方法,因爲對同一業務方法的多次調用會產生不必要的複雜性。如何在不使用定時器的情況下在Windows服務中創建循環
所以我在on_start中添加了do-while循環。我知道這不是正確的方式,因爲它產生了這個過程,如果服務關閉,它將成爲孤兒。
我該如何解決這個問題?
問候, 澤
我想每10秒鐘從Windows服務(使用C#和.NET完成)調用業務層方法。但是,我不想使用Timer_Elapsed事件,因爲它啓動另一個線程/進程,如果第一個線程/進程仍在運行。我只需要一種單線程方法,因爲對同一業務方法的多次調用會產生不必要的複雜性。如何在不使用定時器的情況下在Windows服務中創建循環
所以我在on_start中添加了do-while循環。我知道這不是正確的方式,因爲它產生了這個過程,如果服務關閉,它將成爲孤兒。
我該如何解決這個問題?
問候, 澤
還有另一種獲得定時執行的方法,WaitHandle.WaitOne()方法提供了一個超時參數。這在服務中可以很好地工作,因爲它可以讓您實現在單個方法調用中停止服務和的定期執行。模板看起來是這樣的:
Thread Worker;
AutoResetEvent StopRequest = new AutoResetEvent(false);
protected override void OnStart(string[] args) {
// Start the worker thread
Worker = new Thread(DoWork);
Worker.Start();
}
protected override void OnStop() {
// Signal worker to stop and wait until it does
StopRequest.Set();
Worker.Join();
}
private void DoWork(object arg) {
// Worker thread loop
for (;;) {
// Run this code once every 10 seconds or stop right away if the service
// is stopped
if (StopRequest.WaitOne(10000)) return;
// Do work...
//...
}
}
有沒有人在行動中得到過這個實例? – Junto 2010-10-12 14:26:43
基於上面的代碼,我得到了一個在我公司運行的服務。它工作正常。 – thd 2011-02-27 11:34:55
如果「做功」需要超過10秒鐘,會發生什麼情況? – vampire203 2015-02-27 20:45:51
使用一個定時器,但只要你進入定時器處理方法,禁用定時器,使得沒有更多的事件被觸發。在退出處理程序之前,重新啓用計時器。
謝謝。但是,如果我這樣做,它會調用業務方法一次,然後再也不會運行? Business方法依次讀取或寫入串行端口,因此應在一次讀/寫/超時後返回,並在一段時間後重復。 – Chakra 2010-01-09 09:16:47
它@Chakravarthy:提供你重新啓用計時器,在離開處理程序之前,它將繼續運行。 – 2010-01-09 09:22:09
由於處理程序方法是在單獨的線程上調用的,因此理論上可以在禁用定時器之前多次調用它。 – 2010-01-09 09:22:55
退房this discussion,尤其是jsw的回答。它提出了一種同步機制來防止同時調用業務邏輯。僅在Elapsed
處理程序方法中禁用定時器並不能保證阻止並行調用,因爲處理程序是在單獨的線程上調用的。按照jsw的建議使用鎖,並在同步代碼塊內停止計時器。
或者,您可以使用Timer
並將AutoReset
屬性設置爲false
。這樣,Elapsed
事件只會引發一次,您可以手動重置計時器以處理方法結束。
+1。好點。 – 2010-01-09 10:13:46
while(true)
{
..do something
Thread.sleep(some time or day);
}
Thread thread;
private void DoWork(object arg)
{
while (true)
{
// Run this code once every 20 seconds or stop if the service is stopped
try
{
Thread.Sleep(20000);
//Do work....
}
catch(ThreadInterruptedException)
{
return;
}
}
}
protected override void OnStart(string[] args)
{
// Start the thread
thread = new Thread(DoWork);
mWorker.Start();
}
protected override void OnStop()
{
// interrupt thread and wait until it does
thread.Interrupt();
thread.Join();
}
如果你想只使用一個線程,則循環聽起來像是正確的做法 - 我假設你已經包括調用了Thread.Sleep保證該方法不是在緊密循環中調用的。你能否提供你如何調用業務層方法的細節?如果你正在調用它,那麼這應該會給你想要的結果。 – 2010-01-09 08:57:34
好的謝謝。我正在調用它。但是,我發現即使我關閉了它在任務管理器中運行的服務。 我正在嘗試通過在調用業務方法時切換的標誌,並且除非標誌已被重置,否則不要再次調用它。我希望它能起作用。否則,我會嘗試你所建議的。問題是Business方法讀取和寫入串行端口,直到它獲取數據或超時。 – Chakra 2010-01-09 09:16:02