10
votes

TRAVAILLEUR SYNCHRONISANT AVEC FIL UI

Travailler sur un projet existant, je dois utiliser des Winforms (je n'ai pas travaillé avec elle pendant un moment) et j'ai un problème de synchronisation avec le fil de l'interface utilisateur.

Le design que je dois m'intégrer avec Fonctionne comme suit: Un travailleur d'arrière-plan obtient un action comme paramètre et l'exécute de manière asynchrone. L'action que je travaille a deux parties; une classe de base (contenant la logique commerciale) et une partie d'interface graphique étant notifiée par le noyau via des événements s'il doit demander une interaction utilisateur.

J'ai ajouté la création de la poignée au constructeur de la forme xxx

avec ceci, suivant fonctionne de code: xxx

pour cet exemple, l'emplacement de démarrage a été défini sur Windows Par défaut. < / p>

si je le change à: xxx

parentwindow est une instance de iwin32window et le Windowstartuplocation est défini sur Centre-parent . Je reçois une exception transversale lors de l'appelant form.invoke (action) .

Fonctionnement transversal non valide: Contrôle 'ActivationConfirmationFormation "accessible à partir d'un fil autre que le thread qu'il a été créé.

questions:

  • Pourquoi existe-t-il une exception de fil croisée uniquement lors du réglage de l'emplacement de démarrage comme CentreParent ? Et comment puis-je l'éviter?
  • pourquoi est formide.invokéréquiitée toujours false ?

    Les deux sont probablement liés!?

    [modifier] @RENIUZ: Tu n'as rien manqué ici;) L'appel est en cours d'édition d'un auditeur étant averti par le noyau xxx

    tout à ma disposition est dans l'interface GUI xxx < / p>


6 commentaires

Est-ce que l'exception transversale de filetage en raison du molletparent ou parce que vous définissez la fenêtre parente (c'est-à-dire toujours enflammer si vous supprimez le paramètre CentreParent )?


@Strillo il fait toujours tomber lors de la réglage du parentwindow


former des invoques à se montrer? Ou iam manque quelque chose ici? Pouvez-vous poster tous les codes?


@Reniuz J'ai ajouté la réponse dans le poste lui-même (pour des raisons de formatage ...)


Je pense que le problème pourrait être que vous essayez d'accéder à une fenêtre (parentwindow) pour laquelle vous n'avez pas de poignée. Et si vous essayez d'exposer la méthode CreateHandle pour la fenêtre mère, puis appelez-la dans votre code enfant soit dans le constructeur, soit avant d'exécuter votre action?


@Strillo Malheureusement, je ne peux pas exposer une telle fonction et rester générique. Je l'utiliserai sans le parentwindow.


4 Réponses :


1
votes

OK, je n'ai aucune autorisation de "commentaire" car je suis un nouvel utilisateur, je vais donc simplement utiliser cet espace de réponse.

Vous créez une nouvelle instance d'une formulaire ActivationConfirmationfirmationfirmationFormation, selon laquelle vous êtes enfoncé, la création de ce formulaire et l'exécution de showdialog s'exécute dans le même contexte de thread, car cela est vrai, le fichier invoquentiel (voir MSDN) est vrai. Evidemment, allez être faux puisque la forme que vous souhaitez accéder est créée dans le fil dans lequel vous y accédez. Pas besoin d'utiliser Invoke / Begininvoke, etc. Quelque @Reniuz a été inquiété.


0 commentaires

1
votes

La forme appartient à un fil différent au parent.

Il apparaît que WinForms CentreParrent Position Position L'argument appelle à l'objet Winforms .NET plutôt que de l'utilisation de l'API Win32 pour trouver la position de la fenêtre parente à partir du HWND, et cet appel transversal est ce qui provoque l'exception de fil croisée. < / p>

La vraie réponse est les threads de travailleurs ne devraient pas avoir de l'interface utilisateur. Ils devraient donner un résultat qui indique que l'intervention de l'utilisateur est requise et que le thread principal devrait s'occuper de l'interaction de l'utilisateur.

omettre cela, ne pas définir une fenêtre parent pour l'interface graphique de fil de travail. Cela pourrait (juste) être fonctionnel si vous n'avez qu'un seul fil ouvrier, mais cela causera toutes sortes de confusion si vous en avez plus qu'aucun.

Si vous devez absolument, utilisez P / invoke pour trouver la position actuelle de la fenêtre de la fenêtre parente de la Win32API et définissez-la explicitement.


0 commentaires

4
votes

Voir formulaire.Invokequikequired à False est le noyau de votre problème. Vous savez que cela doit être vrai. L'explication simple est que l'objet de formulaire transmis à votre méthode ShowDialog () est le mauvais objet. L'erreur classique est d'utiliser neuf pour créer l'instance au lieu d'utiliser l'instance existante de l'objet de formulaire, celle que l'utilisateur examine et a été créée sur le fil principal. Assurez-vous que le code fileté a une référence à cet objet de forme afin qu'il puisse transmettre la référence correcte. Utilisez uniquement Application.OpenForms [0] si vous ne pouvez pas le faire correctement.

En général, découplez le code fileté de l'interface utilisateur. Un fil de travail n'a aucune entreprise affichant une boîte de dialogue. Vous pouvez le faire fonctionner mais cela ne fonctionne pas bien dans la pratique. La boîte de dialogue apparaît sans que l'utilisateur l'attend. Faire probablement des accidents, l'utilisateur peut cliquer sur une touche une fraction d'une seconde avant que la boîte de dialogue apparaisse. Rejeter la boîte de dialogue sans même le voir. Le CreateHandle () hack de la même manière doit pas dans votre code. Il suffit de ne pas démarrer le fil avant que l'interface utilisateur soit prête. Signalé par l'événement de charge du formulaire.


1 commentaires

Merci d'avoir expliqué! Le formulaire est en fait créé à la volée dans la partie graphique du travailleur et non par le fil de l'interface graphique. Ceci est une question de conception que je ne peux pas changer. Les utilisateurs devront vivre avec les dialogues sur l'emplacement de Windows par défaut;)



0
votes

comme suivi:
J'ai maintenant une solution de travail (le dialogue n'était pas modal sans définir le parent). Je conviendrai que ce n'est pas la plus belle chose de lancer un dialogue d'un fil de travail, mais dans ce cas, c'est une exigence. Parentform est désormais un formulaire, par opposition à un iWin32Window avant

Créer le dialogue dans le fil graphique: xxx

appelez le dialogue du fil d'interface utilisateur < Pré> xxx

Comme toutes les substances graphiques sont effectuées dans le fil de l'interface utilisateur, la création de la poignée n'est plus requise.


0 commentaires