[英]Is there anything wrong with creating a timer for each instance?
為了更好地理解,我將以DHCP租約的簡單抽象為例:租約包含IP和MAC地址,它被授予的時間,並且可以在給定的時間跨度內更新。 一旦過期,將調用一個事件。 同樣,這只是我能想到的最小的例子:
using System;
using System.Net;
using System.Net.NetworkInformation;
using System.Timers;
namespace Example
{
public class Lease
{
public IPAddress IP
{
get;
private set;
}
public PhysicalAddress MAC
{
get;
private set;
}
public DateTime Granted
{
get;
private set;
}
public event EventHandler Expired;
private readonly Timer timer;
public Lease(IPAddress ip, PhysicalAddress mac, TimeSpan available)
{
IP = ip;
MAC = mac;
timer = new Timer();
timer.AutoReset = false;
timer.Elapsed += timerElapsed;
Renew(available);
}
public void timerElapsed(object sender, EventArgs e)
{
var handle = Expired;
if (handle != null)
{
handle(this, EventArgs.Empty);
}
}
public void Renew(TimeSpan available)
{
Granted = DateTime.Now;
timer.Interval = available.TotalMilliseconds;
timer.Enabled = true;
}
}
}
創建時有什么需要考慮的 - 例如 - 這類課程的“幾千個”實例嗎? 我最關心的是計時器。 我是否應該為這樣的任務考慮另一種設計模式 (比如所有租約的經理,或者根本不使用計時器?) 或者在創建大量計時器時沒有什么可擔心的,這是合適的方法嗎? 至少我總是試圖在計時器和事件時保持謹慎。
您可以只存儲每個Lease
對象的到期時間,而不是創建數千個計時器,然后定期在單個線程查詢中查找已過期的對象。
在我的頭部代碼示例的頂部:
var leases = new List<Lease>();
var running = true;
var expiredChecker = Task.Factory.StartNew(() =>
{
while (running)
{
var expired = leases.All(l => l.ExpirationDate < DateTime.Now);
// do something with the expired lease objects
}
});
假設您的Lease
對象上有一個IEnumerable<Lease>
,一個名為ExpirationDate
的DateTime
屬性,則可以通過在要停止時將運行設置為false來取消它。
根據System.Timers.Timer
MSDN頁面 :
基於服務器的Timer設計用於多線程環境中的工作線程。 服務器計時器可以在線程之間移動以處理引發的Elapsed事件,從而在准時引發事件時比Windows計時器更准確。
這意味着當您同時運行幾千個計時器時,它不太可能導致問題。
這並不意味着它是一個好方法,你應該尋找一個更集中的解決方案來解決這個問題。
我建議使用System.Threading.Timer
而不是System.Timers.Timer
。 第二個是關於第一個在設計時可見的包裝器,如果你真的不需要設計時間支持則沒有必要。 Timer內部調用ThreadPool.QueueUseWorkItem ,而線程池負責維護計時器tick上的線程。 線程池只使用一個線程來維護所有的定時器對象,並且該線程決定每個定時器隊列中的新線程何時打開。
我不能看到任何開銷,除非你的計時器打得如此之快,以至於你無法完成所有的工作,而你只是在線程池中排隊太多工作。
我認為這部分取決於您在服務器上可用的資源,以及您需要的准確性和性能。
另一種方法可能是在每個實例中存儲像時間戳一樣簡單的東西,並定期檢查該值,將其與當前時間進行比較,並適當地更新它。 我有預感,這可能會更容易在性能上 - 但你應該嘗試以某種方式對它進行基准測試以確保。
當然,如果你有大量的實例,迭代所有實例也可能需要一些時間,所以可能將這些組合成組,其中每個組在常規(可調節?)間隔的單獨線程中處理可能是一個選項。
如果沒有關於性能的一些信息,在這里給出一個很好的答案有點困難,所以你應該只是創建一個概念證明,並測試你認為可能有效的幾個策略,並嘗試對它們進行基准測試,看看哪個最合適。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.