C# WinForms: How to set Main function STAThreadAttribute
I get the following exception when calling saveFileDialog.ShowDialog()
in a background thread:
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.
According to this:
To fix the problem, insert the statement:
Threading.Thread.CurrentThread.ApartmentState = Threading.ApartmentState.STA;
in Main right before the Application.Run statement.
But the Application.Run statement is in Program.cs which seems to be generated code so any changes might be unexpectedly lost. Also, I could not find a way to set current thread to STA in the project or main form properties but maybe I am looking in the wrong place.
What is the proper way to call saveFileDialog.ShowDialog()
in a background thread?
Solution 1:
Solution very easy;
Just add this on top of the Main method [STAThread]
So your main method should look like this
[STAThread]
static void Main(string[] args)
{
....
}
It works for me.
Solution 2:
ShowDialog() shouldn't be called from a background thread - use Invoke(..).
Invoke((Action)(() => { saveFileDialog.ShowDialog() }));
Solution 3:
this should work if you are creating the thread in which you call the showDialog:
var thread = new Thread(new ParameterizedThreadStart(param => { saveFileDialog.ShowDialog(); }));
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
Solution 4:
Add following code on FormLoad
private void Form1_Load(object sender, EventArgs e)
{
Thread myth;
myth = new Thread(new System.Threading.ThreadStart(CallSaveDialog));
myth.ApartmentState = ApartmentState.STA;
myth.Start();
}
Here CallSaveDialog
is a thread and here you can call ShowDialog
like this
void CallSaveDialog(){saveFileDialog.ShowDialog();}
Solution 5:
On your MainForm:
if (this.InvokeRequired) {
this.Invoke(saveFileDialog.ShowDialog());
} else {
saveFileDialog.ShowDialog();
}
Or, if you will have other methods that need to be run from the UI thread:
private void DoOnUIThread(MethodInvoker d) {
if (this.InvokeRequired) { this.Invoke(d); } else { d(); }
}
Then, call your method as such:
DoOnUIThread(delegate() {
saveFileDialog.ShowDialog();
});