0

I am working with WPF. I run a thread process in the main xaml window using Dispatcher.

Then I got this error for opening another WPF to show the result of displaying a 3D image:

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

This is how I start a new window:

void DisplayFormThread()
{
    IResult result = _mainWindow.GetResult();
    ResultView resultView = new ResultView (result);
    resultView.Show();
}

I have tried to resolve the problem by adding this in some posts on stackoverflow but it does not help:

ThreadStart start = delegate()
{
   DispatcherOperation op = Dispatcher.CurrentDispatcher.BeginInvoke(
        new delegateNewWindow(DisplayFormThread), DispatcherPriority.Background);

        DispatcherOperationStatus status = op.Status;
                   while (status != DispatcherOperationStatus.Completed)
                   {
                            status = op.Wait(TimeSpan.FromMilliseconds(1000));
                            if (status == DispatcherOperationStatus.Aborted)
                            {
                                 // Alert Someone
                            }
                    }

       };

// Create the thread and kick it started!
Thread thread = new Thread(start);
thread.SetApartmentState(ApartmentState.STA);
thread.Start();

How can I solve the problem?

Thanks in advance.

olidev
  • 20,058
  • 51
  • 133
  • 197

3 Answers3

3

The reason is that our newly created thread is not enabled to support WPF window infrastructure. In particular, it provides no support for Windows message pumping,You have to run separate dispatcher for newly created window. Here is sample for this

Firoz
  • 7,224
  • 10
  • 41
  • 56
2

WPF requires that the thred are of STA type, so if you want DisplayFormThread to be called by STA thead you have to do something like this:

Thread newThread = new Thread(new ThreadStart(DisplayFormThread));
newThread.SetApartmentState(ApartmentState.STA);
newThread.Start();

STAThread refers to "Single-Threaded Apartments" which refers to the threading model used by the current (main) thread. Basically, with the [STAThread] declaration, other applications will know what your thread's policy is when sending you data. The STA model is the most common threading model for Windows threads/applications. You can read more about Apartment State here.

gliderkite
  • 8,828
  • 6
  • 44
  • 80
  • thanks for your answer. I already have tried this one as I also added in my question. However, the result in a new window did not show... – olidev Apr 23 '12 at 08:58
0

UI object must be declared in a single thread apartment(sta) and for each STA thread, you must create a new dispatcher.

You must call Dispatcher.Run() inside the action parameters of thread start

ThreadStart start = delegate() {
    DispatcherOperation op = Dispatcher.CurrentDispatcher.BeginInvoke(
    new delegateNewWindow(DisplayFormThread), DispatcherPriority.Background);

    DispatcherOperationStatus status = op.Status;
    while (status != DispatcherOperationStatus.Completed) {
        status = op.Wait(TimeSpan.FromMilliseconds(1000));
        if (status == DispatcherOperationStatus.Aborted) {
            // Alert Someone
        }
    }
    Dispatcher.Run();
};

// Create the thread and kick it started!
Thread thread = new Thread(start);
thread.SetApartmentState(ApartmentState.STA);
thread.Start();

WPF UI thread needs a dispatcher, because dispatcher manages data sharing between multiple UI threads.

Alessio
  • 3,404
  • 19
  • 35
  • 48