问题
I have a options window and a window that displays color based on these options and Kinect data. So far everything's on one thread (as far as I know; I haven't done any threading).
Now, I'm adding an option to open a viewer window that will need to be updated with lowest possible latency. All this entails is creating a window and showing it:
viewer = new SkeletalViewer.MainWindow();
viewer.Show();
When this event fires, the color window stops displaying colors (i.e. the event that fires 30 times a second on the main thread stops firing), but the viewer is displayed perfectly. I want the viewer and the color window to both be updated.
From reading other questions, it sounds like the solution is to create the viewer on a new thread. I'm encountering a lot of problems with this, though.
This fires when I click the button to open the viewer:
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();
}
Regardless of if I just call viewer.Show() or Invoke() it as above, the line throws an exception: Cannot use a DependencyObject that belongs to a different thread than its parent Freezable. Here's how I understand Invoke(): it accesses viewer's dispatcher, which knows what thread the object is running on, and can then call methods from that thread.
Should I be trying to put this viewer on a new thread? Is the problem even a question of threads? The user will not be interacting with the viewer.
Anyone know why this doesn't work? Thanks for the help.
回答1:
You need to call Show()
on the same thread that the window is created on - that's why you are getting the error. Then you also need to start a new Dispatcher instance to get the runtime to manage the window.
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();
}
See the Multiple Windows/Multiple Threads example at: http://msdn.microsoft.com/en-us/library/ms741870.aspx
回答2:
So I was running into a similar issue where a new window failed to open on a new thread. The exception was "cannot use a dependencyobject that belongs to a different thread".
The issue ended up being that the window was using a global resource (Background brush). Once I froze the brush resource, the window loaded just fine.
回答3:
I am not sure if this will solve your problem but can you try creating a thread proc (to open a viewer window) which is executed on a different thread and then have a dispatcher.beginInvoke to update the main window ,
Here is some code-
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
}
With this you can update the main window controls without freezing it, Let me know if you have any questions
来源:https://stackoverflow.com/questions/8957969/how-do-i-open-a-window-on-a-new-thread