Создать таймер в потоке - C#
Формулировка задачи:
У меня есть событие, оно вызывается безусловно в конце очереди других событий.
Проблема в том, что мне нужно чтобы событие вызывалось один раз в конце всех очередей.
Хочу добавить нечто вроде таймера в отдельном потоке, чтобы при обращении к нему из другого потока до истечения времени таймер начинал отсчёт заново, а по истечению времени событие выполнялось. Однако не совсем понимаю как подобное организовать.
Заранее спасибо.
Решение задачи: «Создать таймер в потоке»
textual
Листинг программы
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Bill77
{
public class WatchDog : IDisposable
{
public WatchDog(TimeSpan timeoutInterval)
{
this.TimeOutInterval = timeoutInterval;
this.mMonitorTask = null;
this.mCancellationToken = null;
this.mSignalEvent = new ManualResetEventSlim();
this.Start();
}
public void Dispose()
{
this.Stop();
}
public TimeSpan TimeOutInterval { get; set; }
public event EventHandler TimeIsOut;
public event EventHandler<RemaningTimeChangedEventArgs> TimeChanged;
private Task mMonitorTask;
private CancellationTokenSource mCancellationToken;
private ManualResetEventSlim mSignalEvent;
private void Start()
{
this.mCancellationToken = new CancellationTokenSource();
this.mMonitorTask = Task.Factory.StartNew(this.Monitor, this.mCancellationToken.Token, this.mCancellationToken.Token);
}
private void Stop()
{
if (this.mCancellationToken != null)
{
try
{
this.mCancellationToken.Cancel();
this.mMonitorTask.Wait();
}
catch (AggregateException exc)
{
if (this.mMonitorTask.IsCanceled)
{
}
}
catch (Exception exc)
{
}
finally
{
this.mCancellationToken.Dispose();
this.mMonitorTask.Dispose();
}
}
}
public void Signal()
{
this.mSignalEvent.Set();
}
private void Monitor(object ct)
{
CancellationToken token = (CancellationToken)ct;
DateTime? lastSignalTime = null;
while (true)
{
token.ThrowIfCancellationRequested();
if (this.mSignalEvent.Wait(100, token))
{
this.mSignalEvent.Reset();
lastSignalTime = DateTime.Now;
}
if (lastSignalTime.HasValue)
{
if (lastSignalTime.Value.Add(this.TimeOutInterval) < DateTime.Now)
{
this.TimeIsOut?.Invoke(this, EventArgs.Empty);
lastSignalTime = null;
}
else
{
TimeSpan remaining = lastSignalTime.Value.Add(this.TimeOutInterval).Subtract(DateTime.Now);
this.TimeChanged?.Invoke(this, new RemaningTimeChangedEventArgs(remaining));
}
}
}
}
public class RemaningTimeChangedEventArgs : EventArgs
{
public RemaningTimeChangedEventArgs(TimeSpan remainingTime)
{
this.RemainingTime = remainingTime;
}
public TimeSpan RemainingTime { get; private set; }
}
}
}