14
votes

I have a WPF application in which a thread checks some value. In certain cases, I show a pop-up Window in order to display a message. When I create this pop-up window in the thread, an exception is thrown by the pop-up window's constructor:

"The calling thread must be STA, because many UI components require this."

How do I resolve this error?

This is my code for creating the pop-up window:

// using System.Threading;
// using System.Windows.Threading;
Thread Messagethread = new Thread(new ThreadStart(delegate()
{
    DispatcherOperation DispacherOP = 
        frmMassenger.Dispatcher.BeginInvoke(
            DispatcherPriority.Normal,
            new Action(delegate()
            {
                frmMassenger.Show();
            }));
}));
Messagethread.Start();
2
I found Problem Root. I have a timer which in the each timer.tick , check for new message`s and then show each new message. Timer thread make my work so hard.Rev
Off-topic: In WPF, windows are called just that: "windows"; not "forms". That latter term is used in another UI framework, Windows Forms.stakx - no longer contributing

2 Answers

14
votes

For the thread that you're trying to start the GUI element in, you need to set the apartment state of the thread to STA BEFORE you start it.

Example:

myThread.SetApartmentState(ApartmentState.STA);
myThread.Start();
10
votes

Absolutely Dispatcher is only way to do something (in specific Thread) when we work with multi-threading in WPF!

But for work with Dispatcher we must know 2 things:

  1. Too many way to use Dispatcher like Dispatcher_Operation , [window.dispatcher] or etc.
  2. We must call dispatcher in the main thread of app (that thread is must be STA thread)

So for example: if we want show other window[wpf] in another thread, we can use this code:

Frmexample frmexample = new Frmexample();
            frmexample .Dispatcher.BeginInvoke //Updated the variable name
                (System.Windows.Threading.DispatcherPriority.Normal,
                (Action)(() =>
                {
                    frmexample.Show();
                    //---or do any thing you want with that form
                }
                ));

Tip: Remember - we can't access any fields or properties from out dispatcher, so use that wisely