2012-02-04 6 views
2

Являются ли таймеры в .NET безопасными для отказа без вызова Dispose() или Close()?Можно ли безопасно отключить таймер

static System.Timers.Timer timer = new Timer(); 

void Main() 
{ 
    timer.Elapsed += LogTimer_Elapsed(object, System.Timers.ElapsedEventArgs); 
    timer.Start(); 
    Thread.Sleep(10000); // Simulate doing something on main thread 
} 

static void LogTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 
{ 
    DoStuff(); 
} 

У кого-нибудь есть проблемы с этим решением?

static QueueLogger() 
{ 
    LogQueue = new Queue<KeyValuePair<Logger, LogEntry>>(50); 
    LogTimer = new Timer(); 
    LogTimer.Elapsed +=new System.Timers.ElapsedEventHandler(LogTimer_Elapsed); 
    AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit); 
} 

static void CurrentDomain_ProcessExit(object sender, EventArgs e) 
{ 
    LogTimer.Stop(); 
    LogTimer.Dispose(); 
    LogTimer_Elapsed(sender, null); // This is to process any remaining messages in the queue 
} 

static void LogTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 
{ 
    lock (_locker) 
    { 
     while (LogQueue.Count > 0) 
     { 
      var queuedLogger = LogQueue.Dequeue(); 
      try 
      { 
       if (e != null) queuedLogger.Value.Message += " From " + sender.ToString(); 
       queuedLogger.Key.Log(queuedLogger.Value); 
      } 
      catch (Exception ex) 
      { 
       OnLoggingError(queuedLogger.Key, "Async Logging error", ex); 
      } 
     } 
    } 
} 
+2

Таймер не является проблемой. Реальный вопрос: безопасен ли код, который вы запускаете в событии Elapsed, прервать, когда процесс завершается. Может быть, невозможно сказать. Не делайте ничего подобного обновлению базы данных или записи в файл. –

+0

@ Hans: Собственно, написание в файл точно, что бы было сделано. Вот идея. Я хотел расширить структуру ведения журнала, чтобы разрешить асинхронное ведение журнала с использованием таймера и очереди. Но я не хотел, чтобы пользователь сети протоколирования беспокоился об утилизации, поскольку ни один из других типов регистраторов не нуждается в этом. – galford13x

ответ

1

Galford,

Да, вы можете создать новое событие, которое будет срабатывать, если ваше приложение о выходе, например, OnExit и прислушайтесь к событию, когда основной поток приложения будет закрыт. Как только это будет сделано, вы можете создать логику событий и выполнить свой таймер, бизнес или очистить логику в событии OnExit. Надеюсь это поможет.

С уважением

+0

Спасибо, я думаю, это может решить проблему. – galford13x

+0

Где находится обработчик событий OnExit, который я должен использовать? – galford13x

+0

Вы можете прикрепить или провод к событию завершения процесса AppDomain, как показано ниже, статической силы основных (String [] арг) { AppDomain.CurrentDomain.ProcessExit + = новый EventHandler (Application_OnExit); // сделать некоторую работу } недействительным Application_OnExit (объект отправителя, EventArgs е) { // сделать таймер очистить и т.д. } –

1

Если вы не утилизируете его явно, оно будет очищено в очереди финализатора сборщика мусора. Хотя это «безопасно», вы понесете штраф за исполнение. Лучше всего использовать свой таймер.

+0

Есть ли способ узнать, выходит ли приложение?Моя цель - написать библиотеку, которая будет использовать таймер, чтобы периодически что-то делать, но я не хочу, чтобы пользователю требовалось распоряжаться и очищать что-либо в библиотеке. – galford13x

+0

Какое наказание это принесет? – weston

+0

@ galford13x Почему вы не хотите, чтобы пользователь чистил вещи? Так работает шаблон IDisposable. Любой класс, который должен освободить системный ресурс, должен делать это через свой финализатор, поэтому вы не получаете hosed, если кто-то забывает распоряжаться объектом. – roken

1

От http://msdn.microsoft.com/en-us/library/system.threading.timer.aspx:

«Когда таймер больше не требуется, не использовать Dispose метод для освобождения ресурсов, проводимых с помощью таймера.»

Итак, если вы хотите, чтобы ваш таймер работал до конца программы, вам не нужно беспокоиться об этом.

0

Сбор мусора очистит таймер, если вы его не избавитесь. Если таймер находится в .exe, и процесс будет просто завершен, когда таймер закончится, вам действительно не о чем беспокоиться. Если вы написали библиотеку, на которую будет ссылаться таймер, вы захотите избавиться от нее, чтобы освободить ресурсы, чтобы сделать вашу библиотеку более эффективной.

0

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

Вызов Dispose() обычно связан с оптимизацией использования памяти, однако в некоторых случаях вызов Dispose() не приведет к неправильной работе вашего программного обеспечения. Например: поскольку количество портов Ethernet ограничено, а не освобождение их после использования может привести к тому, что система закончится из сетевых портов. Это обычно называется «Исключение TCP/IP-порта» и может возникать, если вы не вызываете Dispose() для управляемых объектов, которые используют сетевые ресурсы (например, WCF-клиенты).

Как правило, всегда разумно вызывать Dispose(), когда вам больше не нужен какой-либо объект, который класс реализует IDisposable. (или использовать его в блоке {}).

В примере, который вы указали, кажется, что ваша переменная таймера статична и привязана к основному потоку. Также кажется, что вы используете свой таймер в конце своей программы. Поэтому в этом конкретном случае это действительно не имеет значения.

+0

Предоставленный код должен был предоставить простой пример. Я вижу вашу точку зрения. В моем случае у меня есть отдельная сборка, которая обеспечивает возможность ведения журнала. Я хотел бы расширить сборку, добавив асинхронный регистратор. Вообще говоря, большинству регистраторов не требуется специальный код завершения, который обычно содержится в структуре ведения журнала. Я не хотел добавлять требование к этой уже простой простой структуре. – galford13x

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