2010-01-26 66 views
2

我有一個.NET Windows服務,它有一個間隔設置爲10秒的計時器。每10秒鐘查詢數據庫以完成任何工作,挑選前3個工作項並處理它們。處理每個工作項目所需的時間取決於用戶。它可能從幾秒到幾分鐘不等。什麼是最佳的計時器間隔? .NET Windows服務

我覺得10秒太短。我選擇了一個較低的時間間隔,因爲用戶正在等待流程完成(他們在前端看到了一個進度條),並且服務獲得工作的速度越快越好。此外,工作項目的數量(三個)隨機挑選。

我確實在我的代碼中「鎖定(this)」,以防止一個線程跨越另一個線程。生產環境中的持續時間短爲10秒嗎?

編輯:另外,它是否有意義,我每次只挑選3件物品進行處理。

+0

如果您的計時器每10秒運行一次,但由於某些原因需要30秒來處理請求,會發生什麼情況? – 2010-01-26 20:44:42

+0

完全取決於完成查詢和通信步驟需要多長時間(只需查詢數據庫是否爲本地服務)以及該過程是如何資源密集型的。 – Jay 2010-01-26 20:45:14

+0

我忘記提及查詢數據庫並不是它唯一的功能,它也啓動了一個可能需要幾分鐘的過程 – Nick 2010-01-26 20:46:25

回答

1

...此外,它讓我感到每採摘要處理的時間只有3項...

有項目的硬一些回暖可能是危險的感覺。您有可能讓項目進入隊列的速度比可以處理的速度快。考慮一下,如果超過三個項目每10秒排隊一次,會發生什麼情況。你會開始看到一個項目需要更長和更長的時間來處理。

生成其他線程或使用事件驅動方法可能會更好。

0

我想這將取決於你的查詢有多複雜。如果這是一個簡單的查詢,它可以立即返回,並且每10秒鐘只能由一個服務運行,但我懷疑這會是一個問題,但我對您的環境一無所知,所以請不要這樣做。

如果您正在尋找其他解決方案,您可以查看消息體系結構而不是輪詢。

基本上,在這種情況下,無論你有什麼系統將工作添加到數據庫中,都可以向服務發出消息,讓它知道有工作要做。然後你的服務不需要輪詢任何東西,它只是坐着等待一個需要檢查數據庫的通知。 或者,您可以在消息本身中包含要做的工作,並讓服務處理它並存儲需要存儲在數據庫本身中的內容。

如果您對消息感興趣,請查看NServiceBus。它基本上是MSMQ的一個包裝,它將打開你的想法,進入一個關於內部連接系統的全新理念世界。

這些選項真的是無窮無盡的。

+0

作爲消息的一部分發送工作的一個問題是,如果服務關閉,待辦任務可能會丟失。另外,如果處理服務不能接收消息,它可能永遠不會意識到有工作要做,從而導致從未處理的任務。將消息隊列放置在中央持久性存儲庫中 - 例如數據庫=),可以防止出現這些問題。 – 2010-01-26 20:55:34

+0

恰恰相反。如果您使用像MSMQ這樣的實際消息服務,則可確保交付。如果服務停止或者不在聽,或者無論情況如何,它都會在下一個機會中選擇它。 – 2010-01-27 13:12:00

0

我會使用10秒的時間間隔。
當用戶進程已經完成(防止不必要的10秒等待)時再次檢查

您可以查看SQLDependency類來捕獲數據庫事件。這會更好,但實施起來更難。

有關SQLDependecy看看這裏的更多信息:
http://www.codeproject.com/KB/database/chatter.aspx

1

我目前正在處理這樣的事情在工作中,與主計時器從存儲過程中獲取的工作要做每一秒(1000毫秒) 。

雖然,提取不限於X項(如你的例子中的3)。
我只是根據需要添加儘可能多的線程,並讓框架正確處理它們。

我試圖解耦所有代碼的方式,我不需要使用任何lock

我保存到數據庫的所有日誌信息,我有另一個計時器(30分鐘間隔)最終提取錯誤並將它們郵寄給我。

假設您將所有工作交給另一個與定時器不同的線程,您應該沒有1秒定時器的問題。

+0

+1非常好的解決方案。 – Walter 2010-01-28 23:08:46

0

這是一個很難回答的問題;您的生產環境可能具有比您的比較環境更大的硬件配置,因此您的隊列可以比當前值更快地處理。

如果你不想猜,試着實現一個基於隊列的winservice。該服務將讀取一個MSMQ隊列並在時間處理一個工作項目並對其進行處理。所以你只需要問那個隊列,如果你還有工作項目要處理,你可以用任何你想要的頻率來做,比如1秒。

最重要的事情是要確保你不要去獲得更多的工作項目,而你仍然有工作要做..

順便說一句,你應該閱讀本:Why lock(this) is bad

1

您的服務時間間隔應獨立於用戶界面。實現這一目標的一種方法是爲數據庫中的每個工作項目設置一個標誌,將其標記爲「新建」,「正在處理」或「已完成」。讓您的服務一次拾取一個項目並將其標記爲「正在處理中」,執行所需的任何操作,並在完成時將其標記爲「已完成」。

然後,您的用戶界面只會輪詢該表並根據需要更新每個最近修改的行的狀態。

通過這種方式,您的計時器間隔對於UI延遲以外的任何考慮都變得無關緊要。您還可以在不犧牲效率的情況下運行多個服務線程(如果您一次只處理一個線程,而不是一個線程抓取三個線程,則三個線程可以處理三個線程),競爭條件很少或沒有機會等等。

此外,一定要在處理時禁用計時器,否則會冒着讓您的進程方法重入(中斷自身)的風險。

+0

這正是我如何實現這一點。 「通過這種方式,除了UI延遲之外,您的定時器間隔將變得無關緊要。」 - >是的,但我不想讓用戶等待太久。 如果每個線程拾取1個項目,則認爲最少需要30秒(在最壞的情況下)處理第3個項目,所以第3個用戶等待這麼久。有可能所有3個請求都可以在10秒內完成,在這種情況下,如果一個線程挑選3個項目會更好嗎? – Nick 2010-01-26 20:54:14

+0

我不同意最好每次做3次。理想情況下,與所需的處理時間相比,您的讀取/更新時間應該是微不足道的。除非有顯着的性能優勢,否則我會避免任意選擇X個項目。在上面的示例中,用戶界面可以通過某種旋轉的「工作」指示器顯示「正在處理」的項目,進一步改善UI體驗。如果3個核心上有3個線程,每個項目幾乎將同時完成。希望這可以幫助。 – 2010-01-26 20:58:15

相關問題