Italiano - English

Eccezione non gestita di tipo 'System.Threading.ThreadStateException' in System.

Un workaround per utilizzare oggetti COM in esecuzione dal debug di Visual Studio 8 (2005). 

Descrizione

Con Microsoft Visual C++ 8(2005), quando una una applicazione /CLR viene eseguita dal debugger e si utilizza un oggetto COM come ad esempio una finestra di dialogo, a runtime viene lanciata la seguente eccezione.

Eccezione non gestita di tipo 'System.Threading.ThreadStateException' in System.Windows.Forms.dll

Informazioni aggiuntive: Prima di effettuare chiamate OLE, occorre impostare il thread corrente sulla modalità Single Thread Apartment (STA). Assicurarsi che la funzione Main sia contrassegnata con STAThreadAttribute. Eccezione generata solo se un debugger è associato al processo.

ciò accade anche se la modalità STA è correttamente impostata nel modo seguente:

[STAThreadAttribute]
int main(array ^args)
{

  //this return MTA if debugger is active
  Threading::ApartmentState AState = Threading::Thread::CurrentThread->GetApartmentState();

 Corpo della funzione main

}

Soluzione

Pare che il Framework .NET 2.0 ignori STAThreadAttribute impostando comunque la modalità MTA, ma solo se l'applicazione viene lanciata dal debugger. 

Per forzare la creazione del thread principale sulla modalita STA è necessario inizializzare manualmente l'ambiente COM sul thread, nel seguente modo:

#include   //richiesto per CoUninitialize e CoInitialize  

[STAThreadAttribute] int main(array ^args)
{
  // Attivare gli effetti visivi di Windows XP prima di creare i controlli
  Application::EnableVisualStyles();   
  Application::SetCompatibleTextRenderingDefault(false);    //this return MTA if debugger is active  
  Threading::ApartmentState AState = Threading::Thread::CurrentThread->GetApartmentState();    
  
  // Creare la finestra principale ed eseguirla
  /*
  per qualche bug o motivo sconosciuto, in fase di esecuzione da debug,
  il tread principale viene impostato come MTA (MultiThreadApparment) anche se
  configurato con [STAThreadAttribute].
  Cio' impedisce di lanciare oggetti COM (esempio finestre di dialogo) in  fase di debug.
  La soluzione seguente è un workaround a questo problema
  */
  if(AState !=(Threading::ApartmentState::STA))
  {
    CoUninitialize(); 
    CoInitialize(NULL);
  }   
  //now this return STA if debugger is active   
  Threading::ApartmentState AState = Threading::Thread::CurrentThread->GetApartmentState();    
  Application::Run(gcnew Form1());    
  
  CoUninitialize();   //probabilmente non è necessario
  return 0; 
  }

Non è molto chiaro il motivo per cui questo è necessario, quindi perchè funziona, tuttavia, dopo aver perso moltissimo tempo a risolvere il problema, si accetta di utilizzare questo workaround. Se qualche lettore vuole aggiungere maggiori dettagli, può farlo nei commenti in fondo alla pagina.

Vota questa pagina:

1 Commenti:

#1 Inviato da goldfishka 06-05-2011

Thank you, very nice post.

Lascia il tuo commento:

Note:
  • La tua email non è obligatoria e non sarà visibile in alcun modo
  • Si prega di inviare solo commenti relativi a questa pagina
  • Commenti inappropriati o offensivi saranno modificati o eliminati
  • Codici HTML non sono consentiti. Prego usare i BB code:
    [b]bold[/b], [u]underline[/u], [i]italic[/i], [code]code[/code]
Il codice, le illustrazioni e gli esempi riportati in questa pagina sono solo a scopo illustrativo. L'autore non prende alcuna responsabilità per il loro utilizzo da parte dell'utente finale.
Questo materiale è di proprietà di Pk Lab ed è utilizzabile liberamente a condizione di citarne la fonte.