Как мне безопасно утилизировать System.Timers.Timer? - PullRequest
9 голосов
/ 25 ноября 2010

Когда вы используете «сырой» таймер .net, вы можете передать дескриптор ожидания, который будет вызван после уничтожения таймера Win32, и вы можете предположить, что ваш обратный вызов не будет вызван. (И таймер будет считаться "мертвым" по ГХ)

Как мне сделать это с System.Timers.Timer?

Ответы [ 2 ]

3 голосов
/ 25 ноября 2010

Установите флаг перед вызовом dispose и отметьте этот флаг в прошедшем обработчике.Даже если таймер сработает, этот флаг предотвратит запуск любого связанного кода обработчика.Вы можете формализовать этот шаблон, написав оболочку для таймера.

Убедитесь, что ваш флаг помечен как изменчивый, поскольку к нему будут обращаться из разных потоков.

0 голосов
/ 25 ноября 2010

Поскольку System.Timers.Timer и System.Windows.Forms.Timer оба используют ThreadPool, он не имеет дескриптора таймера операционной системы, поэтому нет собственного ресурса таймера, который удаляется - просто завершенный поток. Я не уверен, что вы можете перехватить поток, перерабатываемый ThreadPool, но я могу ошибаться.

Возможно, вы можете свернуть свои собственные (я не проверял это, и использование ManualResetEvent в Dispose может быть более полезным):

void Run()
{
    ManualResetEvent resetEvent = new ManualResetEvent(false);

    System.Threading.Timer timer = new System.Threading.Timer(delegate { Console.WriteLine("Tick"); });
    timer.Dispose(resetEvent);

    MyTimer t = new MyTimer();
    t.Interval = 1000;
    t.Elapsed += delegate { t.Dispose(resetEvent); };

    resetEvent.WaitOne();
}


public class MyTimer : System.Timers.Timer
{
    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);
    }

    public virtual void Dispose(WaitHandle handle)
    {
        handle.SafeWaitHandle.Close();
        Dispose();
    }
}
...