Поле сообщения и окно сообщения

В форме WPF мне нужно два сообщения о состоянии в текстовом поле, пока программа выполняет какую-то длительную задачу: «Начало» и «Завершено», чтобы упростить ее. Сообщение отображается в текстовом блоке, привязанном к свойству с OnPropertyChange в установщике, конечно.

Проблема: при изменении этого свойства отображается только второе сообщение.

StatusMessage = "Started";
Thread.Sleep(700); // Searching the harddrives and make some lists in the real prog. 
StatusMessage = "Finished";

Странно для меня: если я поставлю MessageBox.Show между первым изменением свойства и Sleep - что, конечно, не имеет смысла - все работает нормально:

StatusMessage  "Started";
MessageBox.Show("Just click");
Thread.Sleep(700);
StatusMessage  "Finished";

Попытка добиться того же с окном сообщения показывает почти такое же поведение: новое окно открывается, но не заполняется содержимым - если только в код не вставить бессмысленную MessageBox.Show. (Я предполагаю, что это имеет ту же основную причину, поэтому добавьте это в ветку здесь.)

MsgWindow mw = new MsgWindow();
mw.Show();
MessageBox.Show("Just click"); //If I delete this line the window opens without content, color etc.
Thread.Sleep(700);
mw.Close();

Где моя ошибка?


person HogoNice    schedule 22.09.2019    source источник


Ответы (1)


В вашем примере проблема заключается в вызове Thread.Sleep - согласно msdn, это делает следующее:

Приостанавливает текущий поток на указанное время.

Текущий поток — это поток пользовательского интерфейса, который должен быть свободен, чтобы механизм привязки обновлял и отображал ваш Started текст. Однако сразу после вызова OnPropertyChanged поток пользовательского интерфейса приостанавливается и становится свободным только после того, как вы изменили текст на Finished.

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

async/await — ваш друг здесь - следующий пример кода должен работать так, как вы ожидаете

StatusMessage = "Started";
await Task.Delay(700);
StatusMessage = "Finished";

В реальном случае в идеале вы должны иметь возможность смоделировать свой длительный процесс в async манере, чтобы сделать что-то вроде

StatusMessage = "Started";
await DoSomeAsyncWork();
StatusMessage = "Finished";

Или, если ваша работа должна быть синхронной, ее можно обернуть в Task следующим образом:

StatusMessage = "Started";
await Task.Run(() => DoSomeWork());
StatusMessage = "Finished";

Я рекомендую эту статью журнала msdn Best Practices in Asynchronous Programming для несколько советов о том, как правильно использовать async.

person Jeremy Crick    schedule 22.09.2019
comment
Спасибо. Это помогло. - person HogoNice; 24.09.2019