У меня есть следующий код для примера приложения консоли для имитации службы Windows.
class Program
{
private Timer timer;
private object syncRoot = new object();
private bool stopSignalled = false;
private ManualResetEventSlim mre = new ManualResetEventSlim(false);
static void Main(string[] args)
{
Program p = new Program();
p.Start();
Console.ReadLine();
p.Stop();
Console.WriteLine("Stopped at:{0:G}", DateTime.Now);
}
private void Stop()
{
stopSignalled = true;
mre.Wait();
}
private void Timercallback(object state)
{
lock (syncRoot)
{
if (!stopSignalled)
{
Console.WriteLine("Callback invoked at:{0:G}",DateTime.Now);
}
else
{
timer.Dispose(mre.WaitHandle);
Console.WriteLine("Timer disposed at:{0:G}", DateTime.Now);
}
}
}
private void Start()
{
Console.WriteLine("Started at:{0:G}",DateTime.Now);
timer = new Timer(Timercallback,null,TimeSpan.Zero,TimeSpan.FromSeconds(1));
}
}
Я был удивлен, что перегрузка Dispose, которая принимает WaitHandle, никогда не сигнализирует дескриптор при использовании ManualResetEventSlim.Если я изменю код, чтобы использовать вместо него ManualResetEvent, вот так, дескриптор действительно сигнализируется.
class Program
{
private Timer timer;
private object syncRoot = new object();
private bool stopSignalled = false;
private ManualResetEvent mre = new ManualResetEvent(false);
static void Main(string[] args)
{
Program p = new Program();
p.Start();
Console.ReadLine();
p.Stop();
Console.WriteLine("Stopped at:{0:G}", DateTime.Now);
}
private void Stop()
{
stopSignalled = true;
mre.WaitOne();
}
private void Timercallback(object state)
{
lock (syncRoot)
{
if (!stopSignalled)
{
Console.WriteLine("Callback invoked at:{0:G}",DateTime.Now);
}
else
{
timer.Dispose(mre);
Console.WriteLine("Timer disposed at:{0:G}", DateTime.Now);
}
}
}
private void Start()
{
Console.WriteLine("Started at:{0:G}",DateTime.Now);
timer = new Timer(Timercallback,null,TimeSpan.Zero,TimeSpan.FromSeconds(1));
}
}
Что дает!