Anzeige "Warten", Bildschirm in WPF
Ich versuche eine Anzeige bitte warten dialog für einen lange Laufenden Betrieb. Das problem ist, da diese ist single threaded, obwohl ich sagen der WaitScreen anzeigen, das tut Sie nie. Gibt es eine Möglichkeit, die ich ändern kann, die Sicht auf dem Bildschirm und stellen Sie es sofort angezeigt wird? Ich habe die Cursor-Aufrufs als Beispiel. Gleich nachdem ich diesen Aufruf.Cursor der cursor wird sofort aktualisiert. Das ist genau das Verhalten, das ich will.
private void Button_Click(object sender, RoutedEventArgs e)
{
this.Cursor = System.Windows.Input.Cursors.Pen;
WaitScreen.Visibility = Visibility.Visible;
//Do something long here
for (Int32 i = 0; i < 100000000; i++)
{
String s = i.ToString();
}
WaitScreen.Visibility = Visibility.Collapsed;
this.Cursor = System.Windows.Input.Cursors.Arrow;
}
WaitScreen ist nur ein Raster mit einem Z-index von 99, die ich ein-und ausblenden.
update: ich weiß wirklich nicht wollen, zu einem hintergrund-Arbeiter, es sei denn, ich muss. Es gibt eine Reihe von stellen im code, wo diese starten und anhalten auftreten.
- Ich war die gleiche, wenn ich versuche zu tun es single-threaded. Denken, können ändern Sie einfach den cursor. Aber es funktionierte nie wirklich.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Tun es single-threaded ist wirklich das gehen zu sein, ein Schmerz, und es wird nie funktionieren, wie Sie möchten. Das Fenster wird schließlich schwarz in WPF, und das Programm wechselt zu "Reagiert Nicht".
Ich würde empfehlen, mit einem BackgroundWorker, um Ihre lang Laufenden task.
Es ist nicht so kompliziert. So etwas wie dies funktionieren würde.
Können Sie sich dann an die ProgressChanged-Ereignis anzeigen, um eine Fortschritt, wenn Sie möchten (denken Sie daran, WorkerReportsProgress true). Sie können auch ein parameter übergeben werden, um runworkerasync erfasst, wenn Ihre DoWork-Methoden muss ein Objekt (in e.Argument).
Dies ist wirklich der einfachste Weg, anstatt zu versuchen, es zu tun ausgezeichnet eingefädelt.
Habe ich einen Weg gefunden! Dank dieser thread.
Diese Funktion muss aufgerufen werden, direkt vor den lange Laufenden Betrieb. Das wird dann Kraft der UI-thread zu aktualisieren.
Schauen Sie sich meine umfangreichen Forschungen von diesem sehr heiklen Thema. Wenn es nichts, was Sie tun können, um zu verbessern, die tatsächliche Leistungsfähigkeit, haben Sie die folgenden Optionen, um die Anzeige einer wartenden Nachricht:
Option #1 Ausführen einen code für die Anzeige einer wartenden Nachricht synchron in die gleiche Methode, die nicht die eigentliche Aufgabe. Nur setzen Sie diese Zeile vor ein langwieriger Prozess:
Werde es Prozess anstehenden Meldungen auf der main-dispatcher-thread am Ende des Invoke().
Hinweis: Grund für die Auswahl der Anwendung.Aktuelle.Dispatcher Dispatcher aber.CurrentDispatcher erklärt hier.
Option #2 Display ein "Wait" - Bildschirm und update UI (Prozess anstehenden Meldungen).
Tun es WinForms Entwickler ausgeführt - Anwendung.DoEvents Methode. WPF bietet zwei alternativen, um ähnliche Ergebnisse erzielen:
Option #2.1 Mit DispatcherFrame Klasse.
Schauen Sie ein bisschen sperrig Beispiel aus MSDN:
Option #2.2 Aufrufen eine leere Aktion
Finden Sie Diskussionen, die man (2.1 oder 2.2) ist besser hier. IMHO option #1 ist immer noch besser als #2.
Option #3 Anzeige einer wartenden Nachricht in einem separaten Fenster.
Es kommt in handliches, wenn Sie die Anzeige nicht einfach warten, Nachricht, sondern eine animation. Rendern einer animation zum laden in der gleichen Zeit, die wir warten, für eine lange rendering-Vorgang abzuschließen, ist ein problem. Im Grunde brauchen wir zwei rendering-threads. Sie können nicht mehrere rendering-threads in einem einzigen Fenster, aber Sie können Ihre be-animation in einem neuen Fenster mit eigener rendering-thread und machen es so Aussehen, dass es nicht in einem separaten Fenster.
Download WpfLoadingOverlay.zip von dies github (es war ein Beispiel aus dem Artikel "WPF Reaktionsfähigkeit: Asynchrone Laden von Animationen Während der Wiedergabe", aber ich kann ihn nicht finden auf der Web mehr) oder haben einen Blick auf die Haupt-Idee unten:
Weitere option ist, um schreiben Sie Ihre lange-routine läuft als eine Funktion zurückgibt, die
IEnumerable<double>
den Fortschritt anzeigt, und einfach sagen:Darauf hin, dass 30% der Weise durch, zum Beispiel. Sie können dann mit einem WPF-timer, um es auszuführen in den "hintergrund" als co-operative coroutine.
Es ist beschrieben im detail hier, mit Beispiel-code.