Заканчивать мое комплексное исследование этой деликатной темы. Если нет ничего, что вы можете сделать, чтобы улучшить реальную производительность, у вас есть следующие варианты для отображения ожидающего сообщения:
Option # 1 Execute кода для отображения сообщения ожидания синхронно в том же методе, который делает реальную задачу , Просто поместите эту строку перед длительным процессом:
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Normal, (Action)(() => { /* Your code to display a waiting message */ }));
Он будет обрабатывать ожидающие сообщения на главной диспетчерской нити в конце Invoke().
Примечание: Причина выбора приложения.Current.Dispatcher, но диспетчер.CurrentDispatcher объясняется here.
Вариант № 2 Отобразите экран «Подождите» и обновите пользовательский интерфейс (ожидающие обработки сообщения).
Для этого WinForms Разработчик выполнил метод Application.DoEvents. WPF предлагает две альтернативы для достижения аналогичных результатов:
Вариант № 2.1 С использованием DispatcherFrame class.
Проверить немного громоздкий пример из MSDN:
[SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public void DoEvents()
{
DispatcherFrame frame = new DispatcherFrame();
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, new DispatcherOperationCallback(ExitFrame), frame);
Dispatcher.PushFrame(frame);
}
public object ExitFrame(object f)
{
((DispatcherFrame)f).Continue = false;
return null;
}
Вариант № 2,2 запустит пустое действие
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Background, (Action)(() => { }));
См дискуссии, которые один (2,1 или 2,2) лучше here. Вариант IMHO №1 по-прежнему лучше, чем # 2.
Вариант № 3 Отображение ожидающего сообщения в отдельном окне.
Это пригодится, когда вы показываете не простое ожидающее сообщение, а анимацию. Проблема рендеринга анимации загрузки в то же время, что мы ожидаем завершения еще одной длительной операции рендеринга. В принципе, нам нужны два потока рендеринга. Вы не можете иметь несколько потоков рендеринга в одном окне, но вы можете поместить свою анимацию загрузки в новое окно со своим собственным потоком рендеринга и заставить ее выглядеть так, как будто это не отдельное окно.
Скачать WpfLoadingOverlay.zip из this github (это был образец из статьи «WPF Реагирования: асинхронная загрузка анимация во время рендеринга», но я не могу найти его в Интернете больше) или иметь взгляд на основная идея ниже:
public partial class LoadingOverlayWindow : Window
{
/// <summary>
/// Launches a loading window in its own UI thread and positions it over <c>overlayedElement</c>.
/// </summary>
/// <param name="overlayedElement"> An element for overlaying by the waiting form/message </param>
/// <returns> A reference to the created window </returns>
public static LoadingOverlayWindow CreateAsync(FrameworkElement overlayedElement)
{
// Get the coordinates where the loading overlay should be shown
var locationFromScreen = overlayedElement.PointToScreen(new Point(0, 0));
// Launch window in its own thread with a specific size and position
var windowThread = new Thread(() =>
{
var window = new LoadingOverlayWindow
{
Left = locationFromScreen.X,
Top = locationFromScreen.Y,
Width = overlayedElement.ActualWidth,
Height = overlayedElement.ActualHeight
};
window.Show();
window.Closed += window.OnWindowClosed;
Dispatcher.Run();
});
windowThread.SetApartmentState(ApartmentState.STA);
windowThread.Start();
// Wait until the new thread has created the window
while (windowLauncher.Window == null) {}
// The window has been created, so return a reference to it
return windowLauncher.Window;
}
public LoadingOverlayWindow()
{
InitializeComponent();
}
private void OnWindowClosed(object sender, EventArgs args)
{
Dispatcher.InvokeShutdown();
}
}
Я был таким же, когда пытался сделать это однопоточным. Думая, просто измените курсор. Но это действительно не сработало. – Ray