Всем привет! Есть проект работающей службы (win service), в которой предусмотрены несколько операций перевода службы в другой режим, что занимает фиксированный промежуток времени. Я попробовал реализовать таймер, осуществляющий засечку времени ожидания и посылки callback'ов для отрисовки ProgressBar у клиента. Проблема заключается в том, что в некоторых случаях таймер зависает (даже по истечении указанного промежутка времени он не осуществляет перевод службы в нужный режим). Я это склонен считать проблемой многопоточности, но, к большому моему сожалению, я в этой теме новичок. Если у кого-то есть идеи как лучше переработать класс ProgressTimer для повышения надежности -- с радостью выслушаю. класс ProgressInfo, встречающийся в тексте, предназначен для передачи в вызывающий код процента выполнения и отрисовки этого процента на ProgressBar. Код | /// <summary> /// Таймер для генерации событий времени ожидания сервера. /// </summary> public sealed class ProgressTimer : IDisposable { #region Конструкторы /// <summary> /// Конструктор для таймера. /// </summary> /// <param name="pd">Делегат для обратного вызова.</param> /// <param name="minProgress">Процент начала выполнения.</param> /// <param name="maxProgress">Процент конца выполнения.</param> /// <param name="duration">Время выполнения в секундах.</param> /// <param name="period">Время в секундах между вызовами делегатов.</param> public ProgressTimer(ProgressDelegate pd, int minProgress, int maxProgress, int duration, int period) { // Определение внутренних переменных. mProgress = pd; mMinProgress = minProgress; mMaxProgress = maxProgress; mDuration = duration; // Фиксация времени начала отсчета. mBeginTime = DateTime.Now; mCallbackTimer = new TimerCallback(this.FireProcessDelegate); // Создание и инициализация таймера. TimerInfo ti = new TimerInfo(); // Переводим заданные параметры для конструктора в миллисекунды // (умножаем количество секунд на 1000). mServiceTimer = new Timer(mCallbackTimer, ti, period*1000, period*1000); ti.tmr = mServiceTimer; } #endregion #region Закрытые поля /// <summary> /// Ссылка на делегат для обратного вызова. /// </summary> private ProgressDelegate mProgress; /// <summary> /// Процент начала выполнения. /// </summary> private int mMinProgress; /// <summary> /// Процент конца выполнения. /// </summary> private int mMaxProgress; /// <summary> /// Время выполнения в секундах. /// </summary> private int mDuration; /// <summary> /// Время начала работы таймера. /// </summary> private DateTime mBeginTime; /// <summary> /// Объект таймера для выполнения основной работы объекта. /// </summary> private Timer mServiceTimer; /// <summary> /// Делегат для обработки событий таймера. /// </summary> private TimerCallback mCallbackTimer; /// <summary> /// Флаг, свидетельствующий об истечении времени ожидания. /// </summary> private bool mIsTimeElapsed = false; #endregion #region Закрытые методы /// <summary> /// Функция обратного вызова по событию таймера. /// </summary> /// <param name="obj">Экземпляр класса <c>TimerInfo</c> с информацией о таймере.</param> private void FireProcessDelegate(object obj) { var ti = (TimerInfo)obj; ProgressInfo pi; // Текущее время в тиках long curTime = DateTime.Now.Ticks; // Длительность в тиках. long lDuration = mDuration * 10000000; // Если время таймера еще не вышло. if((curTime - mBeginTime.Ticks) < lDuration) { // Вычисляем текущий процент выполнения. pi = new ProgressInfo( (int)(mMinProgress + (mMaxProgress - mMinProgress) * (curTime - mBeginTime.Ticks) / lDuration)); mIsTimeElapsed = false; } // Время таймера истекло. else { // Процент выполнения максимальный. pi = new ProgressInfo(mMaxProgress); // Опускаем флаг завершения промежутка времени. mIsTimeElapsed = true; // Принудительное удаление объекта таймера, // чтобы не происходило зависание при переходе. mServiceTimer.Dispose(); } // Проверка на NULL, чтобы избежать исключений. if(mProgress != null) { mProgress.BeginInvoke(pi, null, null); } } #endregion #region Свойства /// <summary> /// Свойство доступа к флагу истечения промежутка времени. /// </summary> public bool IsTimeElapsed { get{ return mIsTimeElapsed; } } #endregion #region Закрытый класс обработки событий таймера private class TimerInfo { /// <summary> /// Прошедшее время в секундах. /// </summary> public int mElapsedTime = 0; /// <summary> /// Ссылка на объект таймера. При отсутствии таковой /// таймер может быть удален раньше времени сборщиком мусора. /// </summary> public Timer tmr; } #endregion
#region IDisposable Members
/// <summary> /// Помечает объект таймера к удалению. /// </summary> public void Dispose() { mServiceTimer.Dispose(); }
#endregion }
|
Это сообщение отредактировал(а) Unlocker - 10.8.2010, 15:15
Присоединённый файл ( Кол-во скачиваний: 2 )
ProgressTimer.zip 1,69 Kb
--------------------
"Если бы Шекспир был программистом, то фразу "To be or not to be" он написал бы так: 2b | ! 2b."
|