【问题标题】:open another xaml window with STA thread error打开另一个带有 STA 线程错误的 xaml 窗口
【发布时间】:2012-04-23 07:52:12
【问题描述】:

我正在使用 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();

我该如何解决这个问题?

提前致谢。

【问题讨论】:

    标签: wpf dispatcher


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      WPF 要求线程是 STA 类型,因此如果您希望 DisplayFormThread 被 STA 线程调用,您必须执行以下操作:

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

      STAThread 指的是“单线程单元”,指的是当前(主)线程使用的线程模型。基本上,通过 [STAThread] 声明,其他应用程序将在向您发送数据时知道您的线程策略是什么。 STA 模型是 Windows 线程/应用程序最常见的线程模型。你可以阅读更多关于公寓状态here

      【讨论】:

      • 感谢您的回答。我已经尝试过这个,因为我也在我的问题中添加了这个。但是,新窗口中的结果没有显示...
      【解决方案3】:

      UI 对象必须在单线程单元(sta)中声明,并且对于每个 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 线程之间的数据共享。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-01-26
        • 1970-01-01
        • 2022-10-14
        • 1970-01-01
        • 1970-01-01
        • 2018-05-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多