如何打开新线程的窗口

本文关键字:窗口 线程 何打开 新线程 | 更新日期: 2023-09-27 18:20:56

我有一个选项窗口和一个显示基于这些选项和Kinect数据的颜色的窗口。到目前为止,一切都在一个线程上(据我所知,我还没有执行任何线程)。

现在,我添加了一个选项来打开一个查看器窗口,该窗口需要以尽可能低的延迟进行更新。所有这些都需要创建一个窗口并显示出来:

viewer = new SkeletalViewer.MainWindow();
viewer.Show();

当该事件触发时,颜色窗口停止显示颜色(即,在主线程上每秒触发30次的事件停止触发),但查看器显示完美。我希望查看器和颜色窗口都更新。

从阅读其他问题来看,解决方案似乎是在一个新的线程上创建查看器。不过,我在这方面遇到了很多问题。

当我点击按钮打开查看器时,就会触发:

private void launchViewerThread_Click(object sender, RoutedEventArgs e)
    {
        Thread viewerThread = new Thread(delegate()
        {
            viewer = new SkeletalViewer.MainWindow();
            viewer.Dispatcher.Invoke(new Action(delegate() 
                {
                    viewer.Show();
                }));
        });
        viewerThread.SetApartmentState(ApartmentState.STA); // needs to be STA or throws exception
        viewerThread.Start();
    }

不管我是否只是打电话给观众。如上所述显示()或调用(),该行引发异常:不能使用与其父级Freezable不同的线程的DependencyObject以下是我对Invoke()的理解:它访问查看器的调度器,调度器知道对象在哪个线程上运行,然后可以从该线程调用方法。

我应该试着把这个查看器放到一个新的线程上吗?这个问题甚至是线程的问题吗?用户将不会与查看器交互。

有人知道为什么这不起作用吗?谢谢你的帮助。

如何打开新线程的窗口

您需要在创建窗口的同一线程上调用Show(),这就是出现错误的原因。然后,您还需要启动一个新的Dispatcher实例,以获得用于管理窗口的运行时。

private void launchViewerThread_Click(object sender, RoutedEventArgs e)
{
    Thread viewerThread = new Thread(delegate()
    {
        viewer = new SkeletalViewer.MainWindow();
        viewer.Show();
        System.Windows.Threading.Dispatcher.Run();
    });
    viewerThread.SetApartmentState(ApartmentState.STA); // needs to be STA or throws exception
    viewerThread.Start();
}

请参阅以下位置的"多窗口/多线程"示例:http://msdn.microsoft.com/en-us/library/ms741870.aspx

所以我遇到了一个类似的问题,一个新窗口无法在一个新线程上打开。异常为"无法使用属于其他线程的dependencyobject"。

问题最终是该窗口使用了全局资源(背景笔刷)。一旦我冻结了画笔资源,窗口加载得很好。

我不确定这是否能解决你的问题,但你能不能尝试创建一个在不同线程上执行的线程进程(打开查看器窗口),然后用dispatcher.beginInvoke更新主窗口

这是一些代码-

    in the constructor register this
    public MainWindow()
    { 
       UpdateColorDelegate += UpdateColorMethod;
    } 
    // delegate and event to update color on mainwindow 
    public delegate void UpdateColorDelegate(string colorname);
    public event UpdateColorDelegate updateMainWindow;
    // launches a thread to show viewer
    private void launchViewerThread_Click(object sender, RoutedEventArgs e)
    {
        Thread t = new Thread(this.ThreadProc);
        t.Start();
    }
    // thread proc
    public void ThreadProc()
    {
       // code for viewer window
       ...
       // if you want to access any main window elements then just call DispatchToMainThread method
       DispatchToUiThread(color);   
    } 
    // 
    private void DispatchToUiThread(string color)
    {
      if (updateMainWindow != null)
      {
        object[] param = new object[1] { color};
        Dispatcher.BeginInvoke(updateMainWindow, param);
      }
    }
    // update the mainwindow control's from this method
    private void UpdateColorMethod(string colorName)
    {
       // change control or do whatever with main window controls
    } 

有了这个,你可以在不冻结的情况下更新主窗口控件,如果你有任何问题,请告诉我