Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Timer для win service 
:(
    Опции темы
Unlocker
Дата 10.8.2010, 14:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 125
Регистрация: 2.11.2007
Где: Москва - Знаменск (Капустин Яр)

Репутация: нет
Всего: 2



Всем привет!
Есть проект работающей службы (win service), в которой предусмотрены несколько операций перевода службы в другой режим, что занимает фиксированный промежуток времени. Я попробовал реализовать таймер, осуществляющий засечку времени ожидания и посылки callback'ов для отрисовки ProgressBar у клиента. Проблема заключается в том, что в некоторых случаях таймер зависает (даже по истечении указанного промежутка времени он не осуществляет перевод службы в нужный режим).
Я это склонен считать проблемой многопоточности, но, к большому моему сожалению, я в этой теме новичок.
Если у кого-то есть идеи как лучше переработать класс ProgressTimer для повышения надежности -- с радостью выслушаю.
класс ProgressInfo, встречающийся в тексте, предназначен для передачи в вызывающий код процента выполнения и отрисовки этого процента на ProgressBar.  smile 
Код

/// <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."
PM MAIL ICQ Skype GTalk Jabber   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0640 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.