如何打开新线程的窗口
本文关键字:窗口 线程 何打开 新线程 | 更新日期: 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
}
有了这个,你可以在不冻结的情况下更新主窗口控件,如果你有任何问题,请告诉我