2009-08-03 17 views
5

prega di dare un'occhiata al seguente codice:Utilizzando Application.Run() su diversi thread

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); 

Sembra come se tutto funziona benissimo: prima vedo lo splashscreen, poi il MainForm viene avviato. Ma in qualche modo ottengo strani errori, come: elementi grafici (una ProgressBar senza fine) non vengono visualizzati correttamente.
MODIFICA: Ho due barre di avanzamento, una sullo splashscreen, sulla mainform. Entrambi mostrano lo stesso comportamento (sbagliato) in modalità infinita: nessun progresso, solo lo sfondo puro. /EDIT
A mio parere questo è dovuto alla chiamata di Application.Run() su fili diversi. Questi errori possono essere eliminati chiamando qualsiasi funzione/proprietà del mainForm prima di iniziare la splashscreen - come, per esempio

mainForm.Text = mainForm.Text; 

Qualcuno può confermare che questo codice può causare problemi - o che dovrebbe comportarsi bene e non ho cercare l'errore da qualche altra parte?
Ho già cercato implementazioni di splashscreen e so che può essere fatto in modo diverso. Ma sono interessato a capire questa implementazione e i suoi possibili problemi. Grazie!

+0

I barre di avanzamento possono essere un po 'speciali, dal momento che possono eseguire il proprio thread per eseguire questa operazione. Puoi isolare e descrivere cosa succede? Come usare un PB bloccato, aggiungere un PB con valore = 50 ecc. –

risposta

1

OMG, ho trovato la risposta:
Application.EnableVisualStyles(); è stato chiamato nel ctor se il mio mainForm (perché?). Deve essere chiamato prima che vengano creati tutti i controlli. Spostarlo sul static Main() ha fatto il trucco. Gli stili visivi sono necessari per le barre di avanzamento infinite (ProgressBarStyle.Marquee).
Ora questa soluzione splashscreen funziona come dovrebbe.

+0

potrebbe aver funzionato per te. Ma, avrei fatto un po 'diversamente. Presumo che tu voglia mostrare lo splashscreen solo durante il caricamento. Quindi, perché creare un message pump per il thread su cui è stata creata la schermata iniziale. Invece basta chiamarlo su un thread separato chiamando Show e quando hai finito, basta chiamare close. Ora, crea message pump chiamando Application.Run (mainForm) –

+0

Sì, potresti avere ragione. La chiamata aggiuntiva a Application.Run() può essere probabilmente saltata, lo controllerò. – tanascius

3

Vorrei creare il modulo sul thread in cui viene eseguito il Application.Run().

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

Ma ciò che ha davvero bisogno di essere fatto è l'accesso tramite la tecnica InvokeRequired e BeginInvoke. Verifica here.

+0

No, l'ho pensato anch'io ma penso che l'affinità del battistrada sia impostata dal metodo Run. –

+0

Beh, questa è solo la metà. La parte principale è in realtà la parte InvokeRequired come suggerisce l'articolo collegato. –

+0

Sì, per qualsiasi comunicazione tra i 2 thread - come sempre. –

1

Non c'è niente di principalmente sbagliato in quello che stai facendo. Ho trovato l'approccio abbastanza interessante da creare una demo e funziona perfettamente. Posso anche dire che la risposta di kek444 non è il problema. La creazione di SplahForm sul thread principale non ha fatto alcuna differenza.

Quindi immagino sia nel modo in cui controlli la Progressbar, o più in generale come comunichi tra i 2 thread.

+0

C'è una barra di avanzamento sullo splashscreen: in modalità continua non mostra alcun progresso (solo lo sfondo).Più avanti nella mainform c'è anche una barra di progressione che mostra lo stesso comportamento in modalità infinita: niente ... – tanascius

+0

Sto eseguendo un PBar su un timer - nessun problema. Come si spinge nuovi valori? –

+0

Non sto spingendo i valori - ho appena impostato lo stile su ProgressBarStyle.Marquee. – tanascius

4

Il thread su cui il display di SplashForm deve avere un messaggio di pump di Windows per elaborare i messaggi che ogni finestra/controllo produce consuma. Per fare ciò è necessario rendere il thread un thread STA. Prova chiamando SetApartmentStateprima di iniziare il filo

+0

Sto eseguendo uno SplashForm su un thread MTA bene. Avete qualche riferimento sui requisiti MessageLoop e STA/MTA? –

+0

Ho impostato l'ApartmentState utilizzando m_Thread.TrySetApartmentState (ApartmentState.STA); Sfortunatamente non aiuta. – tanascius

+0

Questo è il meglio che ho potuto trovare con una ricerca breve: http://blogs.msdn.com/jfoscoding/archive/2005/04/07/406341.aspx –

Problemi correlati