用STA线程错误打开另一个xaml窗口

时间:2012-04-23 07:52:13

标签: wpf dispatcher

我正在使用WPF。我使用Dispatcher在主xaml窗口中运行一个线程进程。

然后我打开另一个WPF以显示显示3D图像的结果时出现此错误:

  

{“调用线程必须是STA,因为许多UI组件都需要   此。“}

这是我开始一个新窗口的方式:

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

我试图通过在stackoverflow上的一些帖子中添加它来解决这个问题,但它没有帮助:

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();

我该如何解决这个问题?

提前致谢。

3 个答案:

答案 0 :(得分:3)

原因是我们新创建的线程未启用支持WPF窗口基础结构。特别是,它不支持Windows消息抽取,您必须为新创建的窗口运行单独的调度程序。 Here is sample for this

答案 1 :(得分:2)

WPF要求thred是STA类型,所以如果你想让STA调用DisplayFormThread,你必须做这样的事情:

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

STAThread是指“Single-Threaded Apartments”,它指的是当前(主要)线程使用的线程模型。基本上,使用[STAThread]声明,其他应用程序将在发送数据时知道您的线程策略是什么。 STA模型是Windows线程/应用程序最常用的线程模型。您可以阅读有关Apartment State here的更多信息。

答案 2 :(得分:0)

UI对象必须在单线程单元中声明,并且对于每个STA线程,必须创建一个新的调度程序。

您必须在线程启动的动作参数内调用Dispatcher.Run()

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线程需要一个调度程序,因为调度程序管理多个UI线程之间的数据共享。