2015-09-22 2 views
-1

Рассмотрите этот код, который использует класс System.Threading.Timer.законное использование GC.Collect?

mTimer = new System.Threading.Timer(someTimer, null, dueTime.TotalMilliseconds, Timeout.Infinite); 

Теперь у меня есть список с раз каждый день функция таймера необходимо выполнить, а затем он сбрасывает таймер в следующий раз, когда он должен выполнить.

private static void someTimer(object state) 
{ 
    TimeSpan dueTime = GetDueTime(); 
    mTimer = new System.Threading.Timer(someTimer, null,  (int)dueTime.TotalMilliseconds, System.Threading.Timeout.Infinite); 
} 

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

Так что простой GC.Collect (0) исправил его, функция таймера выполняет только один раз. Я знаю, что общепринятое мнение заключается в том, что никогда не нужно использовать вручную вызов сборщика мусора, поэтому мой вопрос в том, является ли это законным использование GC.Collect? Как еще это можно исправить?

+4

Почему вы повторно назначаете таймер вместо его изменения? –

+0

weow. потому что я не знал об изменении функции ... в порядке, без хорошего использования GC.Collect здесь либо – Laurijssen

+0

@RonBeyer Вы должны сделать ответ. – juharr

ответ

3

System.Threading.Timer имеет метод Change, который позволяет вам изменять таймер вместо воссоздания нового.

Проблема, как вы обнаружили в кругу, состоит в том, что только потому, что вы повторно назначаете объект, это не означает, что «старый» не продолжает стрелять. Это связано с привязанными обработчиками событий к объекту (который может содержать объекты зомби в живом виде) или обратным вызовам пула в очереди в этом случае. Dispose не гарантирует, что вы не получите другой обратный вызов, потому что обратные вызовы поставлены в очередь пулом потоков и не будут очищаться, пока вызывающий вызов не будет вызван в следующий раз.

Рекомендуемый способ - использовать функцию изменения.

+1

Как возможно, что 'Timer' запускает событие несколько раз, если период установлен на бесконечный? –

+0

Это не должно быть, отдельные его экземпляры делают это, я не уверен в остальной части кода, несколько мест могут вызвать эту функцию или «сбросить» таймер. –

+0

Если вам нужно какое-то сложное планирование, возможно, попробуйте Quartz.net? –

0

Вы должны Dispose() таймер, когда вы больше не хотите его запускать.

+1

Фактически [docs] (https://msdn.microsoft.com/en-us/library/zb0225y6 (v = vs.110) .aspx) say _Callbacks могут возникать после того, как была вызвана перегрузка метода Dispose() ._ – juharr

+0

@juharr Да, но это не проблема. Примечание в документах касается обычных проблем безопасности потоков - 'Dispose' * будет * предотвращать любые публикации в будущем. Он просто ничего не может сделать о запланированных запросах (очевидно). – Luaan

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