我在 Windows 服务中遇到了 System.Timers.Timer 的问题。我基本上使用以下代码在基本轮询服务类中设置计时器:
_serviceTimer.Elapsed += OnElapsedTime;
_serviceTimer.Interval = ServiceTimerInterval.TotalMilliseconds;
_serviceTimer.AutoReset = false;
_serviceTimer.Enabled = true;
当 OnElapsedTime 触发时,我想禁用计时器并根据查找将间隔设置为不同的值。问题是当我更改间隔时它实际上会重新启动计时器。 msndn 文档中提到了这种奇怪的行为:
注意: 如果 Enabled 和 AutoReset 都设置为 false,并且之前已启用计时器,则设置 Interval 属性会导致 Elapsed 事件引发一次,就好像 Enabled 属性已设置为 true 一样。要在不引发事件的情况下设置时间间隔,您可以暂时将 AutoReset 属性设置为 true。 Timer.Interval
在一次性事件中我有这个:
_serviceTimer.Enabled = false;
double newIntervalSetting = newSetting;
base._serviceTimer.AutoReset = true;
base._serviceTimer.Interval = newIntervalSetting;
base._serviceTimer.AutoReset = false;
//reenable after processing
问题是间隔更改仍然会开始计时器倒计时并最终触发事件,即使我在更改间隔之前将 autoreset 设置为 true。 enabled 始终保持为 false,但事件仍会触发。我不确定我是否误解了有关执行此操作的正确方法的 msdn 文档。谁能帮帮我?
最佳答案
我相信这与 EventHandler 从不同的线程调用有关,而不是当前将 Enabled
设置为 false
的代码。
根据 MSDN Doc :
The signal to raise the Elapsed event is always queued for execution on a ThreadPool thread, so the event-handling method might run on one thread at the same time that a call to the Stop method runs on another thread. This might result in the Elapsed event being raised after the Stop method is called. The code example in the next section shows one way to work around this race condition.
private static void HandleElapsed(object sender, ElapsedEventArgs e)
{
numEvents += 1;
// This example assumes that overlapping events can be
// discarded. That is, if an Elapsed event is raised before
// the previous event is finished processing, the second
// event is ignored.
//
// CompareExchange is used to take control of syncPoint,
// and to determine whether the attempt was successful.
// CompareExchange attempts to put 1 into syncPoint, but
// only if the current value of syncPoint is zero
// (specified by the third parameter). If another thread
// has set syncPoint to 1, or if the control thread has
// set syncPoint to -1, the current event is skipped.
// (Normally it would not be necessary to use a local
// variable for the return value. A local variable is
// used here to determine the reason the event was
// skipped.)
//
int sync = Interlocked.CompareExchange(ref syncPoint, 1, 0);
if (sync == 0)
{
// No other event was executing.
// The event handler simulates an amount of work
// lasting between 50 and 200 milliseconds, so that
// some events will overlap.
int delay = timerIntervalBase
- timerIntervalDelta / 2 + rand.Next(timerIntervalDelta);
Thread.Sleep(delay);
numExecuted += 1;
// Release control of syncPoint.
syncPoint = 0;
}
else
{
if (sync == 1) { numSkipped += 1; } else { numLate += 1; }
}
}
关于c# - System.Timers.Timer 间隔重置导致重启,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5478442/