none
Почему не срабатывает WPF DispatcherTimer? RRS feed

  • Вопрос

  • Здравствуйте.

    У себя в приложении WPF я применяю DispatcherTimer. У меня в приложении выполняются 4 потока, которые запускаются из потока пользовательского интерфейса (UI) по нажатию кнопки на панели управления в главном окне приложения. Я инициализирую таймер в одном из потоковых методов. По срабатыванию таймера предполагаю отрисовывать очередной единичный отрезок на оси X, расположенной на Canvas в главном окне приложения. Это главное окно естественно определяется в потоке (UI). Ниже привожу инициализацию таймера.

    private void TimeAxisMarkup()
    {
       // Таймер единичных отрезков для оси времени. Определяет временной интервал,
       // соответствующий единичному отрезку на оси времени
       DispatcherTimer SessionQuantumTimer = new System.Windows.Threading.DispatcherTimer();
                
       // Подготавливаем таймерк работе.
       SessionQuantumTimer.Tick += new EventHandler(SessionQuantumTimerTick);
       SessionQuantumTimer.Interval = new TimeSpan(0, 0, SessionQuantumTimerSpan);
    
       while (f_Connected)
       {
           if (f_Trade)
           {
              if (!SessionQuantumTimer.IsEnabled)
                    SessionQuantumTimer.Start();
           }
            else
           {
              if(SessionQuantumTimer.IsEnabled)
                    SessionQuantumTimer.Stop();
           }
       }
    }
    

    Обработчик SessionQuantumTimerTick также определен в приложении, но его определение я здесь не привожу. Флаги f_Connected и f_Trade устанавливаются и сбрасываются по нажатию на кнопке на панели в главном окне приложения (т.е. в UI). Во время отладки задаю интервал срабатывания таймера равный 10 секундам. Проблема в том, что таймер не срабатывает вобще, т.е. метод SessionQuantumTimerTick не вызывается ни через 10 секундный интервал ни через какой-либо ещё. Почему? Может стоит определить таймер не в отдельном потоке, а в UI? Если можно - скажите, пожалуйста, в чем дело. Почему таймер не срабатывает по истечению заданного промежутка времени?

    С уважением   Евгений.

     

    12 ноября 2011 г. 14:50

Ответы

  • DispatcherTimer привязан к текущему диспатчеру. Диспатчер же в свою очередь привязан к текущему потоку. Если вы хотите, чтобы таймер срабатывал на вьюшке, то нужно его на ней и создавать (или в её потоке/диспатчере). Если вы будете создавать таймер в отдельном потоке (не в UI потоке), ничего не сработает. Ну, точнее что-то наверняка сработает, но не так как вам захочется :)

    Если же вас нужно создать таймер в отдельном потоке, можно запоминать текущий UI диспатчер и передавать его в нужный поток и уже в этом диспатчере создавать таймер.

    • Помечено в качестве ответа Abolmasov Dmitry 16 ноября 2011 г. 8:00
    14 ноября 2011 г. 9:36
    Отвечающий
  • Здесь приводятся типы приоритетов и их описание, выберите наиболее подходящий для вашей задачи DispatcherPriority - перечисление, если не знаете какой выбрать, укажите Normal или Background.


    Для связи [mail]
    • Помечено в качестве ответа TownSparrow 15 ноября 2011 г. 13:19
    14 ноября 2011 г. 21:26

Все ответы

  • А строка 

      SessionQuantumTimer.Start();

    точно срабатывает?


    Влюблен в WPF
    14 ноября 2011 г. 5:17
    Отвечающий
  • Да, срабатывает. Проверял в отладчике. А то что строка SessionQuantumTimer.Start() находится в потоке внутри цикла - это не мешает запуску SessionQuantumTimerTick по истечению заданного 10-секундного интервала? Вобще, где осуществляется отсчет заданного временного интервала? В том потоке в котором таймер определен и запущен или в потоке пользовательского интерфейса из которого был запущен поток, в котором, в свою очередь, был определен и запущен таймер?



    • Изменено TownSparrow 14 ноября 2011 г. 8:33
    14 ноября 2011 г. 8:10
  • Да не глянул честно на то, что метод Start в цикле. Если верить этой статье, то метод Start сбрасывает значение таймера а значит ваши 10 секунд просто не успевают натикать...
    Влюблен в WPF
    14 ноября 2011 г. 9:07
    Отвечающий
  • DispatcherTimer привязан к текущему диспатчеру. Диспатчер же в свою очередь привязан к текущему потоку. Если вы хотите, чтобы таймер срабатывал на вьюшке, то нужно его на ней и создавать (или в её потоке/диспатчере). Если вы будете создавать таймер в отдельном потоке (не в UI потоке), ничего не сработает. Ну, точнее что-то наверняка сработает, но не так как вам захочется :)

    Если же вас нужно создать таймер в отдельном потоке, можно запоминать текущий UI диспатчер и передавать его в нужный поток и уже в этом диспатчере создавать таймер.

    • Помечено в качестве ответа Abolmasov Dmitry 16 ноября 2011 г. 8:00
    14 ноября 2011 г. 9:36
    Отвечающий
  • Т.е. передать Dispatcher потока UI в качестве параметра в потоковый метод создаваемого потока, а затем в этом потоковом методе создать DispatcherTimer с помощью конструктора? Например, следующего:

     

    public DispatcherTimer(DispatcherPriority priority, Dispatcher dispatcher)
    
    

    А какой, в данном случае, лучше задать приоритет в первом аргументе конструктора - Normal или какой другой из перечня перечисления DispatcherPriority?

     


    • Изменено TownSparrow 14 ноября 2011 г. 17:12
    14 ноября 2011 г. 17:11
  • Здесь приводятся типы приоритетов и их описание, выберите наиболее подходящий для вашей задачи DispatcherPriority - перечисление, если не знаете какой выбрать, укажите Normal или Background.


    Для связи [mail]
    • Помечено в качестве ответа TownSparrow 15 ноября 2011 г. 13:19
    14 ноября 2011 г. 21:26