2010-03-31 1 views
0

Je travaillais depuis un certain temps sur une application héritée et j'ai remarqué un petit problème. Le système est un client/serveur incroyablement complexe avec des frameworks standards et personnalisés.L'application héritée crée des boîtes de dialogue dans un thread non-ui

L'un des cadres personnalisés intégrés à l'application implique la validation des actions de workflow. Il trouve les erreurs potentielles, les sépare en avertissements et erreurs, et transmet les résultats au client. La principale différence entre les avertissements et les erreurs est que les avertissements demandent à l'utilisateur s'il souhaite ignorer l'erreur. Le problème que j'ai, c'est que la boîte de dialogue pour cette invite est créée sur un thread non-ui, et donc nous avons des problèmes d'inter-threading lorsque la boîte de dialogue est affichée. J'ai tenté d'invoquer l'affichage de la boîte de dialogue, mais cela échoue car le handle de fenêtre n'a pas été créé. (InvokeRequired renvoie false, ce qui signifie que dans ce cas, il ne peut pas trouver un handle correct dans son arbre parent, plutôt que de ne pas l'utiliser.)

Est-ce que quelqu'un a des suggestions pour créer cette boîte de dialogue? et obtenir le fil de l'interface utilisateur pour le configurer et l'appeler?

Répondre

1

Je ne suis pas tout à fait clair sur les détails de votre implémentation, mais le code ci-dessous est la façon dont vous géreriez un appel depuis votre thread non-ui vers le thread ui. Cet extrait de code suppose que l'objet "this" est un formulaire Windows et représente le thread ui.

L'idée est que votre thread non-ui appelle la méthode nommée "ShowMessageBox", qui réside sur le ui-thread. Lorsque l'appel arrive, vous vérifiez le this.InvokeRequired à partir d'un objet sur le ui-thread, qui dans cet exemple serait un formulaire Windows. InvokeRequired renverra "true" ce qui entraînerait l'exécution du code dans la première partie de l'instruction if. Ce code invoque un rappel de la fonction ShowMessageBox à partir de l'ui-thread principal en créant un délégué de la même signature que la méthode "ShowMessageBox" et en passant à nouveau l'objet émetteur et les arguments d'événement, en agissant sur l'appel de threads non-ui à l'ui-thread. Cet appel suivant à la méthode "ShowMessageBox" est maintenant "marshalé" à l'ui-thread et contournera la première partie de l'if et passera à l'autre où vous pouvez appeler la boîte de message ou le formulaire ou tout ce dont vous avez besoin.

Profitez-en!

private object _lock = new object(); //should have class scope 

private void ShowMessageBox(object sender, EventArgs e) 
{ 
    if (this.InvokeRequired) 
    { 
    lock (_lock) 
    { 
     EventHandler d = new EventHandler(ShowMessageBox); 
     this.Invoke(d, new object[] { sender, e }); 
     return; 
    } 
    } 
    else 
    { 
    MessageBox.Show("Show some messsage or invoke your form instance."); 
    } 
} 
+0

Cela ne fonctionne pas dans cette situation, comme je l'ai mentionné ci-dessus. Sans un handle de fenêtre, vous ne pouvez pas appeler invoke. – Frater

+2

Avez-vous considéré le modèle ci-dessus et créé une classe EventArgs personnalisée qui passerait un message ou un type enum que vous pourriez ensuite utiliser pour créer l'instance appropriée du formulaire à partir de la partie else de l'instruction if. Cela éviterait votre problème de création du formulaire sur un thread non-ui. Vous ne transmettez qu'une sorte d'indicateur de type ou de message, puis agissez sur ce message à partir de l'ui-thread au lieu d'essayer d'invoquer une instance de formulaire à partir d'un autre thread que celui sur lequel il a été créé. – Doug

+0

Cela pourrait valoir la peine, mais ce serait assez compliqué. Le code est assez horrible. Je vais y réfléchir davantage, merci. – Frater

1

Après avoir créé votre contrôle. La force pour créer la poignée en y accédant est la propriété poignée:

sync = new System.Windows.Forms.Control(); 
var temp = sync.Handle; 

Et alors vous êtes bon pour aller à l'invoquer:

sync.Invoke((Action)(() => { })); 
Questions connexes