我有一个计时器,我试图在 dispose 方法中关闭它,但我需要 100% 确定它已完成运行,并且我们不再有对 ElapsedEventHandler 的杂散回调。 我知道您无法检查回调是否已完成,因此我试图涵盖所有基础,以确保不会发生崩溃并且消息全部从我的队列中删除。
我已经实现了 StopTimer bool,因此在我处理时计时器不会自行重新启动。 我有一个 SemaphoreSlim 阻塞计时器已用方法。 我设置了等于计时器运行时间间隔 2 倍的延迟,以确保计时器应该完成其最后一个周期。
我也不确定这是否是正确的方法,或者我是否应该停止计时器并让 GC 负责清理工作?
public class MessageWriter : IDisposable
{
public delegate void WriteMessageDelegate(OutputMessage messageQueue);
private ConcurrentQueue<OutputMessage> MessageQueue = new ConcurrentQueue<OutputMessage>();
public WriteMessageDelegate OutputToDevice;
private System.Timers.Timer WriteTimer { get; set; }
public int TimerInterval { get; set; }
private SemaphoreSlim WritingMessages;
private bool RunTimer { get; set; }
private bool _disposed = false;
public MessageWriter(double timerInterval)
{
TimerInterval = TimerInterval;
RunTimer = true;
WritingMessages = new SemaphoreSlim(1);
WriteTimer = new System.Timers.Timer();
WriteTimer.AutoReset = false;
WriteTimer.Interval = TimerInterval;
WriteTimer.Elapsed += WriteTimerElapsed;
}
private void WriteTimerElapsed(object sender, ElapsedEventArgs e)
{
try
{
WritingMessages.Wait();
EmptyQueue();
if (RunTimer)
WriteTimer.Start();
}
catch (Exception)
{
//Nothing we can do here, this is the logger
Console.WriteLine("Exception with Log timer - : " + ex.Message);
}
finally
{
WritingMessages.Release();
}
}
private void EmptyQueue()
{
while (MessageQueue.TryDequeue(out var message))
{
OutputToDevice?.Invoke(message);
}
}
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
}
//Prevent timer running again
RunTimer = false;
//Disable timer if its running
if (WriteTimer != null)
{
WriteTimer.Enabled = false;
WriteTimer.Stop();
WriteTimer.Dispose();
}
//Wait for double the timer interval
System.Threading.Thread.Sleep(TimerInterval + TimerInterval);
//Wait until this message writer has finished
WritingMessages.Wait();
//Release the semaphore so the timer can run again if it needs to
WritingMessages.Release();
//Get rid of any messages left in the queue
EmptyQueue();
//Dispose of the delegate
OutputToDevice = null;
// Free any unmanaged objects here.
_disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~MessageWriter()
{
Dispose(false);
}
}
您可以在需要时处置计时器,无需任何额外操作。任何正在进行的 WriteTimerElapsed 都会继续,不再触发任何计时器。
WriteTimerElapsed 应该将消息队列处理至空。
这里没有隐藏风险。