2009-08-03 11 views
5

S'il vous plaît jeter un oeil sur le code suivant:En utilisant Application.Run() sur différents threads

var splashForm = new SplashForm(); 
m_Thread = new Thread(() => System.Windows.Forms.Application.Run(splashForm)) 
m_Thread.Start(); 

// Do some initialization 
// ... 

// the following method just invokes `Close()` on the right thread 
splashForm.Shutdown(); 

// Loop until the thread is no longer alive 
// ... 

System.Windows.Forms.Application.Run(mainForm); 

Il semble que tout fonctionne bien: d'abord je vois le splashscreen, plus tard, le mainform se met en marche. Mais d'une manière ou d'une autre, j'ai des erreurs étranges, comme: les éléments graphiques (un ProgressBar sans fin) ne s'affichent pas correctement.
EDIT: J'ai deux barres de progression, une sur le splashscreen, sur la mainform. Ils montrent tous deux le même (mauvais) comportement en mode sans fin: pas de progrès, juste le fond pur. /EDIT
À mon avis, cela est dû à l'appel de Application.Run() sur différents threads. Ces erreurs peuvent être éliminés en appelant une fonction/propriété du Mainform avant de commencer la splashscreen - comme, par exemple

mainForm.Text = mainForm.Text; 

Quelqu'un peut-il s'il vous plaît confirmer que ce code peut causer des problèmes - ou qu'il doit se comporter bien et je chercher l'erreur ailleurs?
J'ai déjà cherché des implémentations de splashscreen et je sais que cela peut être fait différemment. Mais je suis intéressé à comprendre cette implémentation et ses problèmes éventuels. Merci!

+0

Les barres de progression peuvent être un peu spéciales, car elles peuvent truner leur propre thread pour faire ce truc de marque. Pouvez-vous isoler et décrire ce qui se passe? Comme si vous utilisiez un PB bloqué, ajoutez un PB avec la valeur = 50 etc. –

Répondre

1

OMG, j'ai trouvé la réponse:
Application.EnableVisualStyles(); a été appelé dans le cteur si mon Mainform (POURQUOI?). Il doit être appelé avant que les contrôles ne soient créés. Déplacement à la static Main() a fait l'affaire. Les styles visuels sont requis pour les barres de progression sans fin (ProgressBarStyle.Marquee).
Maintenant, cette solution de splashscreen fonctionne comme il se doit.

+0

cela pourrait avoir travaillé pour vous. Mais, je l'aurais fait un peu différemment. Je suppose que vous voulez montrer l'écran de démarrage seulement pendant le chargement. Alors pourquoi créer une pompe de message pour le fil sur lequel l'écran de démarrage est créé. Au lieu de cela, appelez-le sur un thread séparé en appelant Show et lorsque vous avez terminé, appelez close. Maintenant, créez une pompe de message en appelant Application.Run (mainForm) –

+0

Oui, vous avez peut-être raison. L'appel supplémentaire à Application.Run() peut être probablement ignoré, je vais vérifier cela. – tanascius

3

Je voudrais créer le formulaire sur le thread où le Application.Run() s'exécute.

SplashForm splashForm = null; 
m_Thread = new Thread(delegate { splashForm = new SplashForm(); System.Windows.Forms.Application.Run(splashForm); }); 
m_Thread.Start(); 

Mais ce qui doit vraiment être fait est l'accès via la technique InvokeRequired et BeginInvoke. Vérifiez here.

+0

Non, je le pensais aussi mais je pense que l'affinité de la bande de roulement est définie par la méthode Run. –

+0

Eh bien, ce n'est que la moitié. La partie principale est en fait la partie InvokeRequired comme le suggère l'article lié. –

+0

Oui, pour toute communication entre les 2 discussions - comme toujours. –

1

Il n'y a rien de fondamentalement faux avec ce que vous faites. J'ai trouvé l'approche assez intéressante pour monter une démo, et ça marche très bien. Je peux aussi dire que la réponse de kek444 n'est pas le problème. Créer le SplahForm sur le thread principal n'a fait aucune différence.

Donc je suppose que c'est dans la façon dont vous contrôlez la barre de progression, ou plus généralement dans la façon dont vous communiquez entre les 2 threads.

+0

Il y a une barre de progression sur le splashscreen - en mode continu, il ne montre aucune progression (juste l'arrière-plan).Plus tard dans la mainform il y a aussi une barre de progression qui montre le même comportement en mode sans fin: rien ... – tanascius

+0

Je cours un PBar sur une minuterie - pas de problème. Comment pousses-tu de nouvelles valeurs? –

+0

Je ne pousse pas les valeurs - Je viens de mettre le style à ProgressBarStyle.Marquee. – tanascius

4

L'unité d'exécution sur laquelle votre SplashForm est affiché doit disposer d'une pompe de message Windows pour traiter les messages générés par chaque fenêtre/contrôle. Pour ce faire, vous devez faire du thread un thread STA. Essayez d'appeler SetApartmentStateavant à partir du fil

+0

Je cours très bien une SplashForm sur un thread MTA. Avez-vous des références sur les exigences MessageLoop et STA/MTA? –

+0

J'ai défini l'ApartmentState en utilisant m_Thread.TrySetApartmentState (ApartmentState.STA); Malheureusement, cela n'aide pas. – tanascius

+0

C'est le meilleur que je pourrais trouver avec une recherche courte: http://blogs.msdn.com/jfoscoding/archive/2005/04/07/406341.aspx –

Questions connexes