DispatcherTimer не запускается в приложении wpf
Я недавно реорганизовал свой код WPF, и теперь мой DispatcherTimer перестал работать. Я проверил другие подобные сообщения здесь, но все они, похоже, были проблемы с неправильным набором потоков диспетчера, который я попытался...
Мой код выглядит так:
class MainWindow : Window
{
private async void GoButton_Click(object sender, RoutedEventArgs e)
{
Hide();
m_files = new CopyFilesWindow();
m_files.Show();
m_dispatcherTimer = new DispatcherTimer();
m_dispatcherTimer.Tick += dispatcherTimer_Tick;
m_dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 250);
m_dispatcherTimer.Start();
await SomeLongRunningTask();
m_files.Hide();
Show();
}
(Текущий класс - это мой главный объект Window, который я скрываю на время копирования файла. CopyFilesWindow - это простое окно Xaml, которое содержит элементы управления, которые я изменяю... CopyFilesWindow сама по себе абсолютно ничего не делает.)
По сути, я жду долго выполняемой задачи (копирую кучу больших файлов), и мой DispatcherTimer должен обновлять прогресс в dispatcherTimer_Tick. Тем не менее, я установил точку останова для этой функции, и она не срабатывает.
Я также попытался установить Dispatcher с помощью конструктора следующим образом:
m_dispatcherTimer = new DispatcherTimer(DispatcherPriority.Normal, m_files.Dispatcher);
m_dispatcherTimer = new DispatcherTimer(DispatcherPriority.Normal, this.Dispatcher);
Но ни одна из этих вещей не меняет поведение... оно все равно не срабатывает.
Что я здесь не так делаю?
1 ответ
DispatcherTime
работает на... ветке Dispatcher. Который застрял в ожидании SomeLongRunningTask()
заканчивать.
Действительно, когда вы нажимаете кнопку Go
, это поток диспетчера, который выполняет GoButton_Click
, Таким образом, вы никогда не должны создавать метод, вызываемый пользовательским интерфейсом (поток диспетчера) async
,
private void GoButton_Click(object sender, RoutedEventArgs e)
{
Hide();
m_files = new CopyFilesWindow();
m_files.Show();
m_dispatcherTimer = new DispatcherTimer();
m_dispatcherTimer.Tick += dispatcherTimer_Tick;
m_dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 250);
m_dispatcherTimer.Start();
SomeLongRunningTask.ContinueWith(() =>
{
// Executes this once SomeLongRunningTask is done (even if it raised an exception)
m_files.Hide();
Show();
}, TaskScheduler.FromCurrentSynchronizationContext()); // This paramater is used to specify to run the lambda expression on the UI thread.
}