Compruebe hacia fuera mi exhaustiva investigación de este tema muy delicado. Si no hay nada que puede hacer para mejorar el rendimiento real, tiene las siguientes opciones para mostrar un mensaje en espera:
Opción # 1 ejecutar un código para mostrar un mensaje de espera de forma sincrónica en el mismo método que hace la verdadera tarea . Sólo hay que poner esta línea antes de un largo proceso:
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Normal, (Action)(() => { /* Your code to display a waiting message */ }));
que va a procesar los mensajes pendientes en el hilo principal despachador al final de la Invoke().
Nota: Motivo para seleccionar Application.Current.Dispatcher but Dispatcher.CurrentDispatcher se explica here.
Opción n. ° 2 Muestre una pantalla "Esperar" y actualice la IU (proceso de mensajes pendientes).
Para hacerlo WinForms developers ejecutado Application.DoEvents method. WPF ofrece dos alternativas para lograr resultados similares:
Opción # 2.1 Con el uso de DispatcherFrame class.
Comprobar un poco voluminosos ejemplo de 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;
}
Opción # 2.2 invocar una acción vacía
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Background, (Action)(() => { }));
Ver discusiones que uno (2.1 o 2.2) es mejor here. En mi humilde opinión, la opción n. ° 1 es mejor que la n. ° 2.
Opción # 3 Mostrar un mensaje de espera en una ventana separada.
Resulta útil cuando muestra no un simple mensaje de espera, sino una animación. Presentar una animación de carga al mismo tiempo que estamos esperando que se complete otra operación de representación larga es un problema. Básicamente, necesitamos dos hilos de renderizado. No puede tener múltiples subprocesos de representación en una sola ventana, pero puede colocar su animación de carga en una nueva ventana con su propio subproceso y hacer que parezca que no es una ventana separada.
Descargar WpfLoadingOverlay.zip de this github (que era una muestra del artículo "WPF de respuesta: asincrónicos Cargando Animaciones durante la representación", pero no lo puede encontrar en la web ya no) o echar un vistazo a la idea principal a continuación:
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();
}
}
Yo era el mismo cuando estaba tratando de hacerlo de rosca simple. Pensando, vamos a cambiar el cursor. Pero nunca funcionó realmente. – Ray