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 code> obtient un J'ai ajouté la création de la poignée au constructeur de la forme p> avec ceci, suivant fonctionne de code: p> pour cet exemple, l'emplacement de démarrage a été défini sur Windows Par défaut. < / p> si je le change à: p> où Fonctionnement transversal non valide: Contrôle 'ActivationConfirmationFormation "accessible à partir d'un fil autre que le thread qu'il a été créé. P>
blockQuote> questions: strong> p> Les deux sont probablement liés!? p> [modifier]
@RENIUZ:
Tu n'as rien manqué ici;)
L'appel est en cours d'édition d'un auditeur étant averti par le noyau p> tout à ma disposition est dans l'interface GUI p> action code> 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. P> parentwindow code> est une instance de iwin32window code> et le Windowstartuplocation Code> est défini sur Centre-parent code>. Je reçois une exception transversale lors de l'appelant form.invoke (action) code>. P>
CentreParent code>? Et comment puis-je l'éviter? LI>
formide.invokéréquiitée code> toujours false code>? li>
ul>
4 Réponses :
OK, je n'ai aucune autorisation de "commentaire" car je suis un nouvel utilisateur, je vais donc simplement utiliser cet espace de réponse. P>
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é. P>
La forme appartient à un fil différent au parent. p>
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. P>
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. P>
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. P>
Voir formulaire.Invokequikequired à False em> 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 em> 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. P>
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 em> 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. P>
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;)
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: p> appelez le dialogue du fil d'interface utilisateur p> < Pré> xxx pré> 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. P> P>
Est-ce que l'exception transversale de filetage en raison du
molletparent code> ou parce que vous définissez la fenêtre parente (c'est-à-dire toujours enflammer si vous supprimez le paramètreCentreParent code>)?@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 code> CreateHandle Code> 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.