Search code examples
c#multithreadingthreadpoolparallel.foreachapartment-state

Parallel Foreach throw an ApartmentState exception


I have the following code for creating tabpages to a predefined list:

private void CreateControls()
    {
        Parallel.ForEach(_websites,
            w =>
            {
                var tabPage = new TabPage(w.Name);
                var webBrowser = new WebBrowser();

                webBrowser.Navigate(w.Url);
                tabPage.Controls.Add(webBrowser);
                WebPagesTabControl.TabPages.Add(tabPage);
            });
    }

I am getting the following exception:

cannot be instantiated because the current thread is not in a single-threaded apartment.

What is the correct way to set the apartment state to STA?


Solution

  • What is the correct way to set the apartment state to STA?

    You're asking the wrong question.

    First, you can't set the apartment state for the worker threads used here. You don't own the threads and the state has to be set before the thread starts running.

    But second and more importantly, even if you could set the state, that's only a necessary condition for the objects you're trying to create, not a sufficient one. UI objects not only need to be created in an STA thread, they need to be create in an STA thread that has a message pump. I.e. the main UI thread in your program.

    Unless you want a proliferation of UI threads in your process (and really, you don't…that'd just introduce a whole new host of other problems), the operation you're trying to accomplish here is simply not amenable to the use of Parallel.ForEach() or any other concurrency technique.

    You should just use a regular foreach, and if there's an opportunity for concurrency here (i.e. executing the HTTP requests asynchronously), let the WebBrowser object itself manage that.