2011-01-11 11 views
17

Quando si crea un'applicazione vuota WinForms con Visual Studio, il modello ha l'attributo STAThread nella classe principale dell'applicazione.Perché le applicazioni WinForms STAThread sono predefinite?

Ho letto alcuni documenti a riguardo, ma non sono sicuro di averlo capito.

Davvero ho alcune domande su di esso:

  1. Perché questo attributo aggiunto?
  2. Che cosa significa?
  3. Cosa succede se rimuovi questo attributo?
+2

Possibile duplicato: http://stackoverflow.com/questions/102437/why-do-all-winforms-programs-require-the-stathread-attribute –

+0

@Cody: Sì, scusa, non l'ho visto, ma IMHO questa risposta è molto meglio dell'altra. –

+1

Sì, è giusto. Non ho votato per chiudere perché quelle risposte non erano fantastiche. Il più importante bit di conoscenza da trarre da questa domanda è questo link: http://blogs.msdn.com/b/jfoscoding/archive/2005/04/07/406341.aspx –

risposta

12

1. Perché questo attributo è stato aggiunto?

Perché è richiesto dal modello di oggetti ActiveX. E puoi lasciare i controlli ActiveX su un WinForm (quindi è lì per la compatibilità) OPPURE alcune classi .NET usano controlli nativi che richiedono quell'attributo.

2. Che cosa significa?

Significa che il thread viene eseguito nel single-threaded apartment model.

3. Cosa succede se rimuovi questo attributo?

Se l'attributo viene rimosso, il comportamento non è definito. Il programma potrebbe non riuscire a caso, con messaggi di errore a volte ragionevoli. Ad esempio, le cose potrebbero funzionare ora, quindi rompere con un service pack.

+1

Il problema più grande che si verificherà è l'interoperabilità COM. E non dire che non lo stai facendo e non preoccuparti: Windows ne fa un sacco sotto le coperte. –

+0

Almeno WPF si rifiuta persino di lavorare in MTA e genera subito un'eccezione. Potrebbe essere che anche WinForms lo faccia. – Joey

+1

Non sono solo i controlli ActiveX, molte altre cose dipendono da questo. Gli appunti, Drag + Drop, qualsiasi finestra di dialogo della shell come OpenFileDialog. Inoltre molti wrapper .NET che utilizzano una API COM sotto il cofano. Questo è tutto l'interoperabilità COM che non puoi vedere ma funziona solo correttamente in un thread STA. Anche il CLR ne è a conoscenza, Thread.Join() pompa un ciclo di messaggi per esempio quando viene chiamato su un thread dell'interfaccia utente. –

19

citare an MSDN blog,

Quando viene applicata la STAThreadAttribute, cambia lo stato appartamento del thread corrente sia thread singolo. Senza entrare in un'enorme discussione su COM e threading, questo attributo garantisce il meccanismo di comunicazione tra il thread corrente e altri thread che potrebbero voler parlargli tramite COM. Quando si utilizza Windows Form, a seconda della funzione che si sta utilizzando, è possibile che si stia utilizzando l'interoperabilità COM per comunicare con i componenti del sistema operativo. Buoni esempi di questo sono gli Appunti e le finestre di dialogo dei file.

+0

Sarebbe bello se metti un link al blog nella tua risposta. – GEOCHET

0

Significa che i programmi Windows Form utilizzano uno stato di apartment a thread singolo. MTA e gli stati di appartamenti con thread liberi non sono supportati.

3

3. Cosa succede se si rimuove questo attributo?

Ho solo aggiunto un semplice esempio che dimostra il problema.

Ho creato una semplice app WinForms con un pulsante e un OpenFileDialog. Al clic del pulsante eseguo una discussione che mostra openFileDialog. Lancio l'app con e senza STAThread ei risultati di fare clic sul pulsante sono gli stessi: genera l'eccezione "Operazione cross-thread non valida: controllo 'Form1' a cui si accede da un thread diverso dal thread su cui è stato creato". Sembra che non ci siano differenze. Ma no.

Poi ho cambiato mostra l'OpenFileDialog chiamando il metodo seguito:

private void ShowOFD() 
{ 
    if (InvokeRequired) 
    { 
     BeginInvoke(new Action(ShowOFD)); 
     return; 
    } 

    openFileDialog1.ShowDialog(this); 
} 

Con STAThread funziona bene come previsto. Senza STAThread lancia l'eccezione: "Il thread corrente deve essere impostato sulla modalità STA (Single Thread Apartment) prima che sia possibile effettuare chiamate OLE. Assicurarsi che la funzione Main abbia contrassegnato STAThreadAttribute. Questa eccezione viene sollevata solo se è collegato un debugger al processo ".

Quindi avvio l'app più volte senza debugger (disconnesso da Visual Studio). Una volta l'app si chiudeva silenziosamente, un'altra volta l'app si chiudeva con il messaggio "vshost ha smesso di funzionare"

Problemi correlati