2009-04-24 7 views
6

Comment puis-je forcer l'exécution d'une section de code sur mon thread principal?Forcer l'exécution de code sur le thread principal

Voilà pourquoi je voudrais savoir:

J'ai une boîte de message créé personnalisé qui obtient parfois montré à partir d'un fil qui est pas le fil principal. Cependant, lorsque le constructeur de la boîte de message est appelé, j'obtiens une exception InvalidOperationException disant "Le thread appelant doit être STA, car de nombreux composants de l'interface utilisateur l'exigent." Cela a du sens, les éléments de l'interface utilisateur doivent être gérés sur le thread principal.

Ma fonction MessageBox.ShowMessage (...) est une fonction statique qui crée une instance de ma boîte de message personnalisée et l'affiche. Y at-il quelque chose que je pourrais mettre dans ShowMessage qui forcerait la boîte de message à être créée et montrée sur le fil principal? Ailleurs dans mon code, j'utilise Control.BeginInvoke pour gérer des problèmes similaires, mais puisqu'il s'agit d'une fonction statique, il n'y a pas d'élément d'interface utilisateur déjà existant pour que je puisse appeler BeginInvoke.

Dois-je appeler MessageBox.ShowMessage à partir d'un Control.BeginInvoke? Je préférerais que BeginInvoke (ou un équivalent) soit appelé depuis ShowMessage.

Répondre

5

Il y a quelques options:

  • faire le second thread STA (vous ne pouvez le faire pour votre propre Thread - pas ThreadPool threads) - via .SetApartmentState(ApartmentState.STA);
  • voir si SynchronizationContext.Current est non nul; le cas échéant, utiliser Send/Post
  • passer la forme/contrôle comme une instance ISynchronizeInvoke (peut ne pas appliquer à WPF - Je ne suis pas sûr à 100%)
+0

Avez-vous un lien expliquant comment implémenter la première option? – w4g3n3r

+0

Appelez Thread.SetApartmentState() avant de démarrer le thread. – itowlson

+0

Lors de la création du Thread, appelez simplement .SetApartmentState comme indiqué dans la réponse (éditée). Faites-moi savoir si vous avez besoin de plus d'aide pour créer le fil en premier lieu. –

5

Votre pensée est juste - pour Faites-le fonctionner correctement, vous aurez besoin de l'appeler depuis le fil principal.

La manière la plus simple? Lorsque vous démarrez votre formulaire principal, enregistrez une référence dans une variable statique qui est visible à votre appel ShowMessage(). Ensuite, votre ShowMessage peut faire la norme:

if(myForm.InvokeRequired) 
{ 
    myForm.Invoke(() => ShowMessage(arg1,arg2,arg3)); 
    return; 
} 
.... other code here.... 
+3

Il ne peut pas réellement avoir besoin d'une variable explicite - dans WPF il pourrait utiliser Application.Current.MainWindow, dans WinForms une fenêtre de la collection Application.OpenForms. – itowlson

1

Au lieu d'afficher directement la boîte de message, il suffit d'envoyer un message à votre thread principal, qui signale le thread principal pour afficher une boîte de message.

+0

+ 1 Ceci est en réalité beaucoup moins intrusif IMO – Rick

+0

Pouvez-vous donner un exemple de comment faire cela? – Brabbeldas

Questions connexes