Могу ли я остановить WPF от выполнения действий пользовательского интерфейса в моем коде
У меня проблема, когда генерация отчета и отправка его на принтер занимает несколько секунд (создание контейнера отчетов RDLC выполняется медленно).
Чтобы убедиться, что пользователь знает о том, что происходит, я попытался обновить строку состояния до и после печати //.
Status = "Printing Report.";
OnPropertyChanged("Status");
//Create a hidden window to host the report control
ReportWindow rw = new ReportWindow();
rw.PrintReport();
rw.Close();
Status = "Printing Report complete.";
OnPropertyChanged("Status");
То, что я хотел случиться, было:
- Статус обновляется, показывая, что отчет создается и будет напечатан, как только он будет готов.
- Отчет создается и печатается за несколько секунд.
- Статус обновляется, чтобы показать успех.
Что на самом деле происходит:
- Ничего не отображается в пользовательском интерфейсе
- Через несколько секунд отчет создается и печатается
- Статус обновляется, показывая, что отчет создается и будет напечатан, как только он будет готов.
- Сразу после этого статус обновляется, чтобы показать успех. Это происходит достаточно быстро, так что первое сообщение на экране отображается не более чем для одного обновления экрана; в худшем случае этого никогда не будет видно, если я не прервусь с точкой останова.
У меня раньше были подобные проблемы с тем, что WPF устанавливал приоритеты в выполнении чего-то медленного в потоке пользовательского интерфейса над обновлением пользовательского интерфейса, чтобы показать, что он будет занят в течение нескольких секунд; но в этом случае я не могу удалить тяжелый предмет из потока пользовательского интерфейса (или сделать что-то еще), чтобы избежать проблемы.
1 ответ
... но в этом случае я не могу удалить тяжелый элемент из потока пользовательского интерфейса (или сделать что-то еще), чтобы избежать проблемы
В этом случае вы можете создать новое окно, которое запускается в отдельном потоке, и отображать его во время печати отчета:
Экран ожидания при рендеринге UIElement в WPF
После того, как отчет был напечатан, просто закройте новое окно:
Window tempWindow = null;
Thread newWindowThread = new Thread(new ThreadStart(() =>
{
SynchronizationContext.SetSynchronizationContext(
new DispatcherSynchronizationContext(
Dispatcher.CurrentDispatcher));
tempWindow = new Window();
tempWindow.Content = new ProgressBar() { IsIndeterminate = true };
tempWindow.Closed += (ss, ee) =>
Dispatcher.CurrentDispatcher.BeginInvokeShutdown(DispatcherPriority.Background);
tempWindow.Show();
System.Windows.Threading.Dispatcher.Run();
}));
newWindowThread.SetApartmentState(ApartmentState.STA);
newWindowThread.IsBackground = true;
newWindowThread.Start();
ReportWindow rw = new ReportWindow();
rw.PrintReport();
rw.Close();
if (tempWindow != null)
tempWindow.Dispatcher.Invoke(new Action(() => tempWindow.Close()));