C#计时器的密集停止/启动
我创建了一个看门狗计时器(使用System.Windows.Forms.timer),如果长时间过期而没有接收到一小包数据,它就会触发:C#计时器的密集停止/启动,c#,performance,timer,C#,Performance,Timer,我创建了一个看门狗计时器(使用System.Windows.Forms.timer),如果长时间过期而没有接收到一小包数据,它就会触发: using System.Windows.Forms; public class Watchdog { private Timer Timer; public void Go() { Timer.Start(); } public void Reset() { Timer.St
using System.Windows.Forms;
public class Watchdog
{
private Timer Timer;
public void Go()
{
Timer.Start();
}
public void Reset()
{
Timer.Stop();
Timer.Start();
}
private void OnTimerExpired(object State)
{
Timer.Stop();
DoSomething();
}
public Watchdog()
{
Timer = new Timer();
Timer.Tick += new EventHandler(OnTimerExpired);
Timer.Interval = (1000 * Timeout);
}
}
主代码调用Go()
,然后在每次收到数据包时调用Reset()
。如果计时器过期,则调用OnTimerExpired()
由于每秒可能有数百个数据包接收,并且应用程序的主要任务是响应这些数据包,因此我开始怀疑重置计时器是否不是CPU/OS密集型的
知道用这种方式调用
Timer.Stop()/Timer.Start()
会如何影响性能(在延迟方面)吗?使用一个简单的timespan或整数变量作为标志。当计时器滴答作响时,它会检查秒表对象,以查看自上次使用该标志以来经过了多少时间。如果超过超时值,则触发看门狗代码
现在,当一个新数据包进来时,其他代码可以使用秒表来更新timespan标志值,而不是重置计时器
您还应该将计时器的滴答声间隔设置为实际超时持续时间的1/2左右,或者在事件中设置代码来设置间隔,以便在连接现在断开时,下一个滴答声事件仅在超时几毫秒后发生。否则,在最后一个数据包在滴答声事件后很快到达的情况下,您可能最终等待的时间几乎是超时时间的两倍
知道如何调用Timer.Stop()
/Timer.Start()
这种方式可能会影响性能(在延迟方面)
无
完成这项工作所需的资源量不太可能衡量。除非您有性能问题,否则不要试图解决性能问题,至少要使用软件来分析软件是否存在实际问题。另一种选择是,只要在收到消息时设置一个
布尔
标志。计时器事件处理程序检查该标志,如果未设置,则发出警报。所以你有:
private bool GotAMessage = false;
void MessageReceived()
{
// happens whenever a message is received
GotAMessage = true;
}
void OnTimerExpired(object state)
{
if (!GotAMessage)
{
// didn't receive a message in time.
}
GotAMessage = false;
}
一个更简单的选项是调用WatchDog类上的方法,该方法在收到数据包时更新公共lastPacketReceived值。然后,您只需要在WatchDog类中启动一个计时器,该计时器在每个超时间隔内滴答一次,并将当前时间与lastPacketReceived值进行比较:
public static class WatchDog
{
static object locker = new object();
static long lastPacketReceived;
static Stopwatch stopWatch = new Stopwatch();
static long threshold = 5000;
static WatchDog()
{
Timer watchDogTimer = new Timer(1000);
watchDogTimer.Elapsed += new ElapsedEventHandler(watchDogTimer_Elapsed);
watchDogTimer.Start();
stopWatch.Start();
}
static void watchDogTimer_Elapsed(object sender, ElapsedEventArgs e)
{
lock (locker)
{
if ((stopWatch.ElapsedMilliseconds - lastPacketReceived) > threshold)
{
// threshold exceeded
}
}
}
public static void PacketReceived()
{
lock (locker)
{
lastPacketReceived = stopWatch.ElapsedMilliseconds;
}
}
}
不要为此使用
DateTime
!在夏令时转换期间,以及如果用户更改时钟,您将遇到问题。您最好在程序启动时启动秒表,并在每次收到消息时保存其已用时间值。然后,计时器滴答声可以将当前的已用时间
值与上次收到的消息值进行比较。您是否最好使用System.Debug.Stopwatch
类?