valid una thread subproceso que para not llamó interfaz example diferente cross aplicación aplanó c# multithreading exception folderbrowserdialog

c# - una - Excepción al usar FolderBrowserDialog



ui thread c# (4)

Obtengo la siguiente excepción al intentar usar FolderBrowserDialog: System.Threading.ThreadStateException: Current thread must be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it. This exception is only raised if a debugger is attached to the process. System.Threading.ThreadStateException: Current thread must be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it. This exception is only raised if a debugger is attached to the process.

He buscado en Google este problema ampliamente y las soluciones que todo el mundo sugiere parecen ser colocar [STAThreadAttribute] encima del método Main, eliminar todas las DLL de la carpeta Debug o usar el método Invoke . He intentado todo esto y sigo teniendo la misma excepción.

Aquí está el código:

public partial class Form1 : Form { public event EventHandler ChooseLocationHandler = null; public string DestFolder { set { textBox1.Text = value; } get { return textBox1.Text; } } public Form1() { InitializeComponent(); } private void ChooseLocationButton_Click(object sender, EventArgs e) { if (ChooseLocationHandler != null) ChooseLocationHandler(this, e); } }

Y en mi presentadora es la siguiente:

public partial class Presenter { Form1 myForm; public Presenter() { myForm = new Form1(); myForm.ChooseLocationHandler += ChooseLocationHandler; myForm.Show(); } public void ChooseLocationHandler(object obj, EventArgs e) { Form1 sender = (Form1)obj; FolderBrowserDialog fbd = new FolderBrowserDialog(); fbd.RootFolder = System.Environment.SpecialFolder.MyComputer; fbd.ShowNewFolderButton = true; if (fbd.ShowDialog() == DialogResult.Cancel) return; sender.DestFolder = fbd.SelectedPath; } }

Estoy obteniendo la excepción en fbd.ShowDialog ().


Ahora, verifique todos los archivos DLL en la referencia y elimine el archivo dll que no use.

Eso fue increíble. Nunca podría haber imaginado que esas DLL están causando este problema.


El atributo STAThread debe estar delante de main hasta donde sé.


Esto solucionó mi problema. [STAThread] static void Main ()

Solo una pregunta adicional: ¿por qué no puede Microsoft simplificar las cosas? ¿Están tratando de disgustar a la gente para hacer algo de codificación?


Un subproceso es STA o MTA; no se puede especificar solo para un método, por lo que el atributo debe estar presente en el punto de entrada.

Desde STAThreadAttribute en MSDN :

Aplique este atributo al método del punto de entrada (el método Main () en C # y Visual Basic). No tiene efecto sobre otros métodos.

Si se llama a este código desde un hilo secundario, tiene 3 opciones:

NOTA IMPORTANTE: el código de ejecución de System.Windows.Forms dentro de un subproceso MTA es imprudente, algunas funciones como los diálogos de apertura de archivos (no solo la carpeta) requieren un subproceso MTA para funcionar.

Cambiando tu apartamento de hilo secundario

Si crea el subproceso usted mismo (y no utiliza la especificidad de MTA), podría cambiar su departamento antes de iniciarlo:

var t = new Thread(...); t.SetApartmentState(ApartmentState.STA);

Creando un hilo solo para ello

Si no controlas la creación del hilo, puedes hacerlo en un hilo temporal:

string selectedPath; var t = new Thread((ThreadStart)(() => { FolderBrowserDialog fbd = new FolderBrowserDialog(); fbd.RootFolder = System.Environment.SpecialFolder.MyComputer; fbd.ShowNewFolderButton = true; if (fbd.ShowDialog() == DialogResult.Cancel) return; selectedPath = fbd.SelectedPath; })); t.SetApartmentState(ApartmentState.STA); t.Start(); t.Join(); Console.WriteLine(selectedPath);

Invocando en otro hilo (STA)

Si su hilo principal también contiene código de System.Windows.Forms, podría invocar en su bucle de mensajes para ejecutar su código:

string selectedPath = null; Form f = // Some other form created on an STA thread; f.Invoke(((Action)(() => { FolderBrowserDialog fbd = new FolderBrowserDialog(); fbd.RootFolder = System.Environment.SpecialFolder.MyComputer; fbd.ShowNewFolderButton = true; if (fbd.ShowDialog() == DialogResult.Cancel) return; selectedPath = fbd.SelectedPath; })), null); Console.WriteLine(selectedPath);