Exception when using FolderBrowserDialog

34,079

Solution 1

A thread is either STA or MTA it can't be specified just for one method so the attribute must be present on the entry point.

From STAThreadAttribute in MSDN :

Apply this attribute to the entry point method (the Main() method in C# and Visual Basic). It has no effect on other methods.

If this code is called from a secondary thread you have 3 choices :

IMPORTANT NOTE: Running (as you seem to do) System.Windows.Forms code inside an MTA thread is unwise, some functionalities like file open dialogs (not only folder) require a MTA thread to work.

Changing your secondary thread apartment

If you create the thread yourself (and don't use the specificity of MTA) you could just change it's apartment before starting it :

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

 

Creating a thread just for it

If you don't control the thread creation you could do it in a temporary thread :

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

 

Invoking in another(STA) thread

If your main thread also contain System.Windows.Forms code you could invoke in it's message loop to execute your code :

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

Solution 2

This fixed my issue. [STAThread] static void Main()

Just an extra question: why can't microsoft make things simple? Are they trying to disgust people to do some coding?

Solution 3

I had the same issue with ASP.NET MVC project. When I export my crystal report to some format it shows me the error. What I have done is replace

This:

            SaveFileDialog browser = new SaveFileDialog();
            string fileName = "";

            browser.Filter = "Pdf|*.pdf|Txt|.txt";

            if (browser.ShowDialog() == DialogResult.OK)
            {
                ExportFormatType formatType = ExportFormatType.NoFormat;
                switch (browser.FilterIndex)
                {
                    case 2:
                        formatType = ExportFormatType.WordForWindows;
                        break;
                    case 1:
                        formatType = ExportFormatType.PortableDocFormat;
                        break;
                }

                fileName = browser.FileName;
                crReportDocument.ExportToDisk(formatType, fileName);

Into:

Thread thread = new Thread((ThreadStart)(() =>
            {
                SaveFileDialog browser = new SaveFileDialog();
                string fileName = "";

                browser.Filter = "Pdf|*.pdf|Txt|.txt";

                if (browser.ShowDialog() == DialogResult.OK)
                {
                    ExportFormatType formatType = ExportFormatType.NoFormat;
                    switch (browser.FilterIndex)
                    {
                        case 2:
                            formatType = ExportFormatType.WordForWindows;
                            break;
                        case 1:
                            formatType = ExportFormatType.PortableDocFormat;
                            break;
                    }

                    fileName = browser.FileName;
                    crReportDocument.ExportToDisk(formatType, fileName);
                }
            }));

            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();
            thread.Join();

Solution 4

As simple as the below :

using System.Windows.Forms;
namespace fileConverterBaset64
{
    class Program
    {
        [STAThread]
        static void Main(string[] args)

Add the command [STAThread] before your main method. That's it, it would work.

Solution 5

The STAThread attribute must be in front of main as far as i know.

Share:
34,079

Related videos on Youtube

Daniel
Author by

Daniel

I am a software engineer living in Atlanta, Georgia. I am looking forward to my Mi.Yodeya reputation exceeding my Stack Overflow reputation, because I think that will mean that I am no longer a nerd. My Mi.Yodeya reputation has finally exceeded my SO reputation! I'm not a nerd anymore.

Updated on July 24, 2021

Comments

  • Daniel
    Daniel almost 3 years

    I'm getting the following Exception when trying to use 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.

    I have Googled this problem extensively and the solutions that everybody suggests seem to be to put [STAThreadAttribute] above the Main method, to delete all dll's from the Debug folder, or to use the Invoke method. I have tried all of these, and I still get the same exception.

    Here's the code:

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

    And in my presenter is the following:

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

    I'm getting the Exception on fbd.ShowDialog().

  • Julien Roncaglia
    Julien Roncaglia almost 13 years
    How is your application started ? Just double clicking on it ? If yes where is this code called from ? A background worker, a secondary thread or something like that ? (If you don't know break in visual studio on the line calling the dialog and paste here the entire call stack)
  • Daniel
    Daniel almost 13 years
    The call stack is far to large to fit in this text box. But it is being called from a different thread from the main thread.
  • Julien Roncaglia
    Julien Roncaglia almost 13 years
    So it is where the problem come from, the apartment is a thread state, i'll add 2 or 3 possible solutions to my answer.
  • Julien Roncaglia
    Julien Roncaglia almost 13 years
    Done but as noted in my answer a thread creating forms should be STA in most cases.
  • Daniel
    Daniel almost 13 years
    The temporary thread did the trick! Thanks so much. I'd upvote 100 times if I could.
  • David
    David over 11 years
    This doesn't really answer his specific question... At least it doesn't add to the accepted answer. And complaining or asking "Why can't XXX to XXXX" isn't appropriate for the site.
  • Eric Javier Hernandez Saura
    Eric Javier Hernandez Saura over 11 years
    This don't answer the question, and please limit to just answer the question.
  • toosweetnitemare
    toosweetnitemare over 11 years
    @VirtualBlackFox Thank you so very much for posting your methods on correcting this error. I searched online for a few hours before i found this thread and your post. your suggestion of "Changing your secondary thread apartment If you create the thread yourself (and don't use the specificity of MTA) you could just change it's apartment before starting it : var t = new Thread(...); t.SetApartmentState(ApartmentState.STA);" was just what i needed and fixed my code. Thank you!
  • da_jokker
    da_jokker over 5 years
    Sorry but this DID fix my issue. I was using a console app and needed access to the clipboard. Adding the [STAThread] worked wonderful for me.
  • creyD
    creyD almost 5 years
    Could you please rework the code markup and add a simple explanation to your answer?
  • n00dles
    n00dles over 3 years
    That's exactly what @Eric answered 7 years earlier.
  • Priya
    Priya about 2 years
    Can I also use this with vb.net? I tried creating temp thread Using topForm As New System.Windows.Forms.Form() Dim tempThread As New Thread(New ThreadStart( Sub() Dim dialog As New Windows.Forms.FolderBrowserDialog() Dim result As Windows.Forms.DialogResult = dialog.ShowDialog()..... ))tempThread.Start() tempThread.Join() tempThread.SetApartmentState(ApartmentState.STA) End Using but still it is giving me the same error. :(
  • Priya
    Priya about 2 years
    Thanks for the 3 diffrnt typs. Creating a temp thread worked nw. Format was different in vb.net but I managed it. For the ones, who are interested in vb.net, Using topForm As New System.Windows.Forms.Form() Dim tempThread = New Thread(CType((Sub() Dim dialog As New Windows.Forms.FolderBrowserDialog() ......... End Sub), ThreadStart)) tempThread.SetApartmentState(ApartmentState.STA) tempThread.Start() tempThread.Join() End Using