Erklärung des Problems
Im Rahmen der Entwicklung einer Anwendung musste das folgende Schema implementiert werden:
- Die asynchrone Methode fordert Daten an
- Der Benutzer gibt Daten über die Tastatur ein
- Die Methode empfängt das Eingabeergebnis als Ergebnis der Funktion und fährt an derselben Stelle fort
Zusätzliche Anforderung: Erstellen Sie keine zusätzlichen Fenster.
Es würde einfach erscheinen? Es stellte sich als sehr einfach heraus. Aber das Wichtigste zuerst.
Lösung
Der erste Versuch, dies direkt und ohne Suche im Internet zu tun, führte zu einer Blockierung des Hauptthreads und daher zu nichts Gutem. Und ich wollte gerade ShowDialog verwenden, als ich auf einen Artikel stieß . Der Autor hat sich angesehen, wie ShowDialog in WPF erstellt wird. Was du brauchst!
In seinem Artikel schlägt er vor, eine eigene Implementierung der ShowDialog-Methode zu erstellen
[DllImport("user32")] internal static extern bool EnableWindow(IntPtr hwnd, bool bEnable); public void ShowModal() { IntPtr handle = (new WindowInteropHelper(Application.Current.MainWindow)).Handle; EnableWindow(handle, false); DispatcherFrame frame = new DispatcherFrame(); this.Closed += delegate { EnableWindow(handle, true); frame.Continue = false; }; Show(); Dispatcher.PushFrame(frame); }
Ich brauche keine Fenstersperre, da alles in einem Fenster angezeigt wird und auch ein Rückgabewert erforderlich ist. Wir entfernen etwas zu viel, fügen das richtige hinzu ...
public string GetInput() { var frame = new DispatcherFrame(); ButtonClicked += () => { frame.Continue = false; }; Dispatcher.PushFrame(frame); return Text; }
Dispatcher.PushFrame(frame)
verhindert, dass die GetInput()
-Methode frame.Continue
wird GetInput()
bis frame.Continue
false
. Wenn ein neuer Frame gestartet wird, wird die Hauptschleife angehalten und ein neuer gestartet. Diese Schleife verarbeitet Systemnachrichten, während sich der Ausführungspunkt in der Hauptschleife nicht weiter bewegt. Wenn wir den aktuellen Frame verlassen ( frame.Continue = false
), arbeitet die Hauptschleife an derselben Stelle weiter.
Jetzt bleibt nur noch die Leistung zu überprüfen.
Erstellen Sie in MainWindow eine Schaltfläche und legen Sie einen Handler darauf, der die Aufgabe startet, in der wir uns der Tastatureingabe zuwenden.
Handler-Code:
public RelayCommand ButtonClick => new RelayCommand(() => { Task.Factory.StartNew(() => {
Ich habe diese Lösung verwendet, um Captcha und zusätzlichen Code für die Zwei-Faktor-Authentifizierung einzugeben. Es kann jedoch eine Vielzahl von Anwendungen geben.
! Der Beispielcode enthält Verstöße gegen das mvvm-Prinzip und nicht hart schlagen fehlendes Design
Github-Quellcode: Proof of Concept
Nützliche Links
Artikel "Custom ShowDialog"
Spärliche Beschreibung der DispatcherFrame-Klasse mit maschineller Übersetzung
Das Warten auf die Fertigstellung über das Warten wird in diesem Artikel angegeben.