2011-02-10 5 views
3

, который является правильным подходом к использованию System.Timers.Timer? Я имею в виду ... Я создаю таймер, задаю интервал и метод, который будет вызываться в событии Истекшее.Жизненный цикл System.Timers.Timer

double ms = 1000; 
var t = new System.Timers.Timer(ms); 
t.AutoReset = false; 
t.Elapsed += (sender, e) => { runTask(); }; 
t.Start(); 

Что дальше? Должен ли вызов выходить на Таймер? Я полагаю, я не могу, или событие Elapsed никогда не произойдет. Должен ли я регистрировать таймер в какой-либо глобальной переменной, чтобы избежать потери ссылок на него, и поэтому GC мог бы распоряжаться таймером до вызова Elapsed? И если да, то как я могу распоряжаться таймером после обработки события Elapsed (таким образом моя задача была выполнена)?

ответ

1

Короткий ответ: вам ничего не нужно делать. Он будет собираться сборщиком мусора, когда функция выходит за рамки. Если вы хотите, чтобы он был доступен, тогда вместо этого объявите его в классе.


Обычно, когда вы объявляете таймер на уровне класса, он собирается GC, когда Class Disposed. Однако, если у вас есть DECLARE таймера в функции, то таймер еще работает, но если вы выполняете очень длительный процесс, то GC может Агрессивно Dispose так, вам нужно будет использовать

GC.KeepAlive(youtimer_Instance); 

Посмотрите в конце Timer's Documentatio n для ссылки на этот сценарий.

Комментарии в коде образца говорит:


     Normally, the timer is declared at the class level, 
     so that it stays in scope as long as it is needed. 
     If the timer is declared in a long-running method, 
     KeepAlive must be used to prevent the JIT compiler 
     from allowing aggressive garbage collection to occur 
     before the method ends. 
+0

Это может создать проблему, если Таймер был создан в Форме A, и пользователь выходит из приложения (будет вызывать исключение, если задача пытается получить доступ к элементу управления формой, это случилось со мной однажды). –

+0

@Mohib Sheth: на что я ответил, как защитить таймер от размещения. Чтобы остановить его, вам явно нужно будет вызвать Stop(). Также лучше, если вы можете отказаться от подписки на свой обработчик событий, когда это требуется. Алексис объяснил это .... –

+0

Прокомментированный вами кодовый комментарий больше не присутствует в документации по таймеру. –

0

Вы должны вызвать t.Stop() в Close/Unload вашей формы/страницы или в любом месте, которое вам кажется нужным. Если вы оставите его запущенным, он будет использовать ресурсы без необходимости, а также вы можете получить исключения при закрытии приложения.

4

Если вы используете Таймеры в процессе длительного (например, веб-приложение или служба Windows), если вы не хотите, чтобы память утечки, вам необходимо убедиться, что вы не подписаны с обработчиком прошедших событий таймера, если вы хотите, чтобы сборщик мусора мог восстановить память, выделенную для объекта Timer.

System.Timers.Timer реализует IDisposable, и в данном руководстве содержатся рекомендации, что если у вас есть класс, реализующий IDisposable, любой класс, который имеет зависимость от объекта, реализующего IDisposable, должен реализовать IDisposable сам и вызвать метод Dispose(), когда он сам называется.

Прекрасным примером этого является система System.Timers.Timer. При этом используется System.Threading.Timer под одеялом, и если вы посмотрите рефлектором вы можете увидеть следующее для метода Dispose на System.Timers.Timer

public void Dispose() 
{ 
    this.timerBase.Dispose(); 
} 

Здесь timerBase просто экземпляр System.Threading. Таймер, и поэтому вызов Dispose каскадирует до всех зависимостей класса, реализующего IDisposable.

+0

+1 для указания потребностей, не связанных с подпиской – themarcuz

Смежные вопросы