2010-08-27 13 views
5

Ecco il messaggio di errore che sto riceve quando si tenta di aprire un OpenFileDialog nel mio programma:STAThread manca, ma è lì

"thread corrente deve essere impostato su singolo appartamento filo (STA) modalità prima che OLE le chiamate possono essere effettuate. Assicurarsi che la tua funzione principale ha STAThreadAttribute contrassegnato su di esso.Questa eccezione è solo generato se un debugger è collegato a il processo. "

Il problema con questo messaggio di errore è che il mio metodo principale ha l'attributo STAThread collegato ad esso. Sono in perdita su come gestirlo. Come posso aggiungere qualcosa se è già lì. Raddoppiare non è una buona opzione, e ho provato a cancellarlo, a costruire l'app, aggiungerla e ricostruirla senza successo. Io proprio non capisco.

private void btnOldFind_Click(object sender, EventArgs e) 
{ 
    openFileDialog1.Multiselect = false; 
    openFileDialog1.FileName = ""; 
    openFileDialog1.ShowHelp = false; 
    openFileDialog1.AutoUpgradeEnabled = true; 
    openFileDialog1.InitialDirectory = @"C:\"; 
    openFileDialog1.Filter = "Microsoft Installer (*.msi)|*.msi|All Files (*.*)|*.* "; 
    openFileDialog1.FilterIndex = 1; 
    openFileDialog1.RestoreDirectory = true; 

    if (openFileDialog1.ShowDialog() == DialogResult.OK) 
    { 
     textBoxOldInstallation.Text = openFileDialog1.FileName; 
    } 
} 

e il metodo principale è:

static class Program 
{ 
    /// <summary> 
    /// The main entry point for the application. 
    /// </summary> 
    [STAThread] 
    static void Main() 
    { 
     Application.EnableVisualStyles(); 
     Application.SetCompatibleTextRenderingDefault(false); 
     Application.Run(new Form1()); 
    } 
} 

E non threading è fatto in modo esplicito. Solo un programma piuttosto semplice per essere onesti.

modalità EDIT2 ::

Qui è il messaggio di errore completo che include stack di chiamate

System.Threading.ThreadStateException è stata gestita Messaggio = "thread corrente deve essere impostato su singolo appartamento filo (STA) prima che le chiamate OLE possano essere fatte, assicurati che la tua funzione principale abbia scritto STAThreadAttribute. Questa eccezione viene sollevata solo se un debugger è collegato al processo. " Fonte = "System.Windows.Forms" StackTrace: a System.Windows.Forms.FileDialog.RunDialog (IntPtr hWndOwner) a System.Windows.Forms.CommonDialog.ShowDialog (proprietario IWin32Window) a System.Windows.Forms .CommonDialog.ShowDialog() in MSI_Comparison_GUI.Form1.btnOldFind_Click (mittente dell'oggetto, EventArgs e) in c: \ tfs \ DocuWare .NET \ DocuWare NewGen \ src \ Tools \ MSI_Comparison \ MSI_Comparison_GUI \ Form1.cs: riga 70 in Sistema .Windows.Forms.Control.OnClick (EventArgs e) in System.Windows.Forms.Button.OnClick (EventArgs e) in System.Windows.Forms.Button.OnMouseUp (MouseEventArgs mevent) in System.Windows.Forms. Control.WmMouseUp (Messaggio & m, MouseButto pulsante ns, Int32 scatto) a System.Windows.Forms.Control.WndProc (Messaggio & m) a System.Windows.Forms.ButtonBase.WndProc (Messaggio & m) a System.Windows.Forms.Button.WndProc (Messaggio & m) a System.Windows.Forms.Control.ControlNativeWindow.OnMessage (Messaggio & m) a System.Windows.Forms.Control.ControlNativeWindow.WndProc (Messaggio & m) a System.Windows.Forms.NativeWindow. DebuggableCallback (IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) a System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW (MSG & msg) a System.Windows.Forms.Ap plication.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop (Int32 dwComponentID, Int32 motivo, Int32 pvLoopData) in System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner (motivo Int32, contesto ApplicationContext) a System.Windows.Forms.Application.ThreadContext.RunMessageLoop (motivo Int32, contesto ApplicationContext) a System.Windows.Forms.Application.Run (Form mainForm) a MSI_Comparison_GUI.Program.Main() in c: \ tfs \ DocuWare .NET \ DocuWare NewGen \ src \ Tools \ MSI_Comparison \ MSI_Comparison_GUI \ Program.cs: riga 18 in System.AppDomain._nExecuteAssembly (Assembly Assembly, String [] args) in System.AppDomain .ExecuteAssembly (String assemblyFile, Evidence assemblySecurity, String [] args) a Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() a System.Threading.ThreadHelper.ThreadStart_Context (stato oggetto) a System.Threading.ExecutionContext.Run (ExecutionContext ExecutionContext, ContextCallback callback, Object state) a System.Threading.ThreadHelper.ThreadStart() InnerException:

+0

Puoi mostrarci il codice, come crei il dialogo? E hai creato un altro thread nel tuo programma? –

+0

è stato aggiunto per il tuo piacere di lettura: P – Adkins

+0

Sei sicuro di essere eseguito nel thread principale a quel punto e che openFileDialog1 è stato creato nel thread principale? –

risposta

14

Potrebbe essere che si trovano ad affrontare il seguente problema segnalato su Connect :

.vshost.exe forces wrong threading model used when debugging a .exe if a .dll of the same name exists in same bin directory

Secondo tale problema accade che il processo di hosting di Visual Studio, cioè il myprogram.vshost.exe impone lo stato dell'appartamento sbagliato quando si dispone sia di un myprogram.exe e di un myprogram.dll nella cartella di output.

Il problema potrebbe essere specifico per una qualche versione precedente di Visual Studio (2005), e non sono stato in grado di riprodurre utilizzando VS 2010.

La soluzione ovvia sarebbe quella di cambiare il nome della dll o per spostare la DLL in un'altra cartella.

La situazione potrebbe essersi verificata perché è stato modificato il tipo di output del progetto dalla libreria di classi all'applicazione Windows.

Non è chiaro se questo problema sia confermato o meno da Microsoft, si dice solo che il problema è al di fuori della responsabilità del team di prodotto VS.

+0

@Adkins: Sono solo curioso: questo è stato davvero il problema? Sei su VS 2005 allora? –

+0

Dangit, stavo cercando qualcosa del genere. Il mio fu fallito. – Will

+0

@Hans Passant: Poiché non riesco a riprodurre il problema, è difficile conoscerne la causa, personalmente sospetterei un bug nel meccanismo vshost, ma forse è legato al team di shell della MS. O ad un ingegnere di supporto pigro ;-) –

3

Non posso dire senza codice. Se una console app, aggiungere il seguente prima di chiamare il metodo:

Console.Write(System.Threading.Thread.CurrentThread.ApartmentState); 

altrimenti,

MessageBox.Show(System.Threading.Thread.CurrentThread.ApartmentState); 

e vedere che cosa lo stato di apartment threading davvero è.

+0

Si tratta di un'applicazione di Windows form di base con nessuna filettatura eseguita appositamente. Ho usato quella messagebox come suggerito e mi ha detto che lo stato era MTA. Davvero non capisco come possa essere, come ho detto che Main è contrassegnato con [STAThread] come fatto automaticamente da Visual Studio, e non faccio nessun altro threading di una chiamata di base a un OpenFileDialog. – Adkins

+0

@adkins sei sicuro di non utilizzare una classe framework che maschera il multithreading? Come il BackgroundWorker o usando "BeginInvoke" su un delegato? Il multithreading non avviene solo per caso. Puoi eseguire il debug e lasciare che l'eccezione venga nuovamente generata? Se aggiorni la tua domanda con lo stack di chiamate dall'oggetto di eccezione, posso probabilmente dirti dove si sta verificando la transizione verso MTA, se stai utilizzando una di queste classi di framework per la transizione. – Will

+0

viene aggiunto, ma non è carino. Non uso assolutamente nulla dal momento che questo errore appare. Sto semplicemente caricando il programma e facendo clic su un pulsante per aprire OpenFileDialog. – Adkins

0

Provare a impostare i punti di interruzione nella procedura principale, nel punto in cui viene creata la finestra di dialogo e dove viene utilizzata. Poi guarda in quale thread si trova effettivamente. Controlla anche quale sia il valore di Thread.CurrentThread.GetApartmentState() in quei punti.

+0

come indicato sopra lo stato corrente del thread corrente è MTA, ma non sono sicuro del perché. – Adkins

+0

@Adkins: è MTA in tutte quelle località, anche direttamente nel metodo principale? –

+0

@ 0xA3 Ho inserito il controllo come prima affermazione nel metodo principale ed era MTA. È seriamente l'attributo STAThread, la firma principale, quindi il controllo. – Adkins

6

Hai una traccia di stack impossibile. È chiaro che il threading non è la causa del problema, tutto è in esecuzione sul thread principale e l'attributo [STAThread] sul metodo Main sta impostando lo stato dell'appartamento. La traccia dello stack mostra che è davvero il punto di accesso.

Bene, cattive notizie, qualche tipo di add-on sta abbaiando con il thread principale. Fare qualcosa di brutto come chiamare CoUninitialize troppe volte. Mi è capitato questo caso una volta, mi ci è voluto un mese per trovarlo. Iniziare la diagnosi con Project + Properties, scheda Debug, selezionare "Abilita debug del codice non gestito". Questo ti permette di vedere quali DLL vengono caricate nel tuo programma, viene mostrato nella finestra Output.

Il primo vantaggio è quando il dialogo elenca va bene il tempo prima ma fallisce il secondo volta. Quindi hai una sorta di gestore di estensione della shell che si è intrufolato nel tuo programma. Utilizzare l'utilità AutoRuns di SysInternals e disabilitare qualsiasi gestore di estensione shell non creato da Microsoft.

Diventa più difficile quando la finestra di dialogo si interrompe immediatamente. Quindi utilizzare Debug + Windows + Modules e consultare l'elenco delle DLL. Presta attenzione a dove provengono, mostrato nella colonna Percorso. Diffidare di tutto ciò che non è come una DLL .NET o Microsoft. Soprattutto non avendo un file di simboli quando hai abilitato Microsoft Symbol Server è un vantaggio. Un buon modo per fare qualche progresso con questo è confrontare quella lista con quella che si vede su un'altra macchina che non ha questo problema.

Ho una storia di guerra su questo. Il mio codice COM si bloccava su centinaia di macchine, tutto quello che dovevo fare era un minidump. Mi ci è voluto un mese per scoprire la fonte, un progetto open source chiamato ffdshow. Molto ampiamente distribuito, usando anche nomi diversi. Aveva un bug, chiamando CoUnitialize due volte di troppo. Il bug era presente nelle versioni per due anni, ma è stato risolto circa un anno e mezzo fa. Molto difficile da diagnosticare, non mi sono avvicinato fino a quando non ho iniziato a guardare le vecchie versioni. Se vedi ffdshow nella finestra Modules, allora sei vicino :)

Buona fortuna, facci sapere chi fa il male.

+0

"Hai una traccia dello stack impossibile". Come intendi "impossibile"? La traccia dello stack sembra una normale traccia di debug dello stack ... –

+0

@ 0xA3: impossibile come in "che non dovrebbe mai lamentarsi dello stato dell'appartamento". –

Problemi correlati