ĂnoncĂ© du problĂšme
Dans le cadre du dĂ©veloppement d'une application, il a Ă©tĂ© nĂ©cessaire de mettre en Ćuvre le schĂ©ma suivant:
- La méthode asynchrone demande des données
- L'utilisateur entre des données à partir du clavier
- La mĂ©thode reçoit le rĂ©sultat d'entrĂ©e comme rĂ©sultat de l'exĂ©cution de la fonction et continue du mĂȘme endroit
Condition supplĂ©mentaire: ne crĂ©ez pas de fenĂȘtres supplĂ©mentaires.
Cela semblerait simple? Cela s'est avéré trÚs simple. Mais tout d'abord.
Solution
La premiÚre tentative de le faire de front et sans chercher sur Internet a conduit à un blocage du thread principal, et donc à rien. Et j'étais sur le point d'utiliser ShowDialog, car je suis tombé sur un article . L'auteur a examiné comment ShowDialog est créé dans WPF. Ce dont vous avez besoin!
Dans son article, il propose de créer sa propre implémentation de la méthode ShowDialog
[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); }
Je n'ai pas besoin d'un verrou de fenĂȘtre, car tout est affichĂ© dans une seule fenĂȘtre et une valeur de retour est Ă©galement requise. On enlĂšve un peu trop, on ajoute le bon ...
public string GetInput() { var frame = new DispatcherFrame(); ButtonClicked += () => { frame.Continue = false; }; Dispatcher.PushFrame(frame); return Text; }
Dispatcher.PushFrame(frame)
empĂȘche la mĂ©thode GetInput()
de se GetInput()
jusqu'Ă frame.Continue
que frame.Continue
devienne false
. Lorsqu'une nouvelle image est dĂ©marrĂ©e, la boucle principale s'arrĂȘte et une nouvelle dĂ©marre. Cette boucle traite les messages systĂšme, tandis que le point d'exĂ©cution dans la boucle principale ne se dĂ©place pas plus loin. Lorsque nous frame.Continue = false
image actuelle ( frame.Continue = false
), la boucle principale continue de fonctionner au mĂȘme endroit.
Maintenant, il ne reste plus qu'à vérifier les performances.
Dans MainWindow, créez un bouton et raccrochez un gestionnaire, qui lancera la tùche, dans laquelle nous passerons à la saisie au clavier.
Code du gestionnaire:
public RelayCommand ButtonClick => new RelayCommand(() => { Task.Factory.StartNew(() => {
J'ai utilisé cette solution pour saisir le captcha et le code supplémentaire pour l'authentification à deux facteurs. Mais il peut y avoir un grand nombre d'applications.
! L'exemple de code contient des violations du principe mvvm, et ne frappe pas fort conception manquante
Code source Github: preuve de concept
Liens utiles
Article "Dialogue Show Show personnalisé"
Description limitée de la classe DispatcherFrame à l'aide de la traduction automatique
L'attente de l'achÚvement via l'attente est donnée dans cet article.