If you want to set a thread's apartment model via Thread.CurrentThread.ApartmentState, you need to act quickly

Raymond Chen

Raymond

Welcome to CLR Week 2014.
Don’t worry, it’ll be over in a few days.

A customer wanted to know why their
Folder­Browser­Dialog
was displaying the infamous
Current thread must be set to single thread apartment (STA) mode
before OLE calls can be made
error.

private void btnBrowseFolder_Click(object sender, System.EventArgs e)
{
  Thread.CurrentThread.ApartmentState = ApartmentState.STA;
  FolderBrowserDialog fbd = new FolderBrowserDialog {
    RootFolder = System.Environment.SpecialFolder.MyComputer,
    ShowNewFolderButton = true,
    Description = "Select the awesome folder..."
  };
  DialogResult dr = fbd.ShowDialog();
  ...
}

“Even though we set the
Apartment­State to STA,
the apartment state is still MTA.
Curiously, if we put the above code in a standalone
test program, it works fine.”

The problem is that the customer is changing the apartment
state too late.

On the first call to unmanaged code,
the runtime calls Co­Initialize­Ex
to initialize the COM apartment as either an MTA or an STA apartment.

You can control the type of apartment created

by setting the
System.Threading.ApartmentState property on the thread to MTA,
STA, or Unknown.

Notice that the value you specify in
Current­Thread.Apartment­State
is consulted at the point the runtime initializes the COM apartment
(which occurs on the first call to unmanaged code).
If you change it after the COM apartment has been initialized,
you’re revising the blueprints of a house after it has been built.

The standard way to avoid this problem is to attach the
[STAThread] attribute to your Main
function,
or if you need to set the apartment model of a thread
you created yourself,
call the
Thread.Set­Apartment­State method
before the thread starts.

Raymond Chen
Raymond Chen

Follow Raymond   

0 comments

Comments are closed.