Reputation: 398
I've got method which I'am calling from main thread. This method is creating a new thread. Code looks like this:
MouseCursorWallObject MouseCursorWall = null;
List<MovingRectangle> MovingRectangles = null;
DrawingImage RenderedImage;
public MainWindow()
{
InitializeComponent();
PrepareObjects();
GameLoopRun();
}
private void GameLoopRun()
{
Thread thread = new Thread(() =>
{
while (true)
{
DateTime dtStart = DateTime.Now;
Events();
Update();
Display();
DateTime dtEnd = DateTime.Now;
TimeSpan ts = dtEnd - dtStart;
if (SkipTicks - ts.TotalMilliseconds >= 0)
{
Thread.Sleep((int)(SkipTicks - ts.TotalMilliseconds));
}
}
});
thread.Start();
}
In Display() method i'am trying update Image control. "Display()" method looks like this:
private void Display()
{
DrawingGroup imageDrawings = new DrawingGroup();
// Drawing main canvas
imageDrawings.Children.Add(DrawingObject(500, 350, 0, 0, new Uri(@"Images\gameCanvas.jpg", UriKind.Relative)));
// Drawing mouse cursor wall
imageDrawings.Children.Add(DrawingObject(MouseCursorWall.Width, MouseCursorWall.Height, MouseCursorWall.GetLocX, MouseCursorWall.GetLocY, MouseCursorWall.DisplayTexture));
for (int i = 0; i < MovingRectangles.Count; i++)
{
MovingRectangle o = MovingRectangles[i];
// Drawing moving object
imageDrawings.Children.Add(DrawingObject(20, 20, o.GetLocX, o.GetLocY, o.TextureUri));
}
if (GamePause == true)
{
}
RenderedImage = new DrawingImage(imageDrawings);
// Image control on main UI thread
renderImage.Dispatcher.Invoke(() =>
{
renderImage.Source = RenderedImage;
});
}
The problem is when I'am trying update Image control using Dispatcher.Invoke I'am receiving error "The calling thread cannot access this object because a different thread owns it". I was trying a lot of different options, and only one works fine:
private void Display()
{
this.Dispatcher.Invoke(() => {
DrawingGroup imageDrawings = new DrawingGroup();
// Drawing main canvas
imageDrawings.Children.Add(DrawingObject(500, 350, 0, 0, new Uri(@"Images\gameCanvas.jpg", UriKind.Relative)));
// Drawing mouse cursor wall
imageDrawings.Children.Add(DrawingObject(MouseCursorWall.Width, MouseCursorWall.Height, MouseCursorWall.GetLocX, MouseCursorWall.GetLocY, MouseCursorWall.DisplayTexture));
for (int i = 0; i < MovingRectangles.Count; i++)
{
MovingRectangle o = MovingRectangles[i];
// Drawing moving object
imageDrawings.Children.Add(DrawingObject(20, 20, o.GetLocX, o.GetLocY, o.TextureUri));
}
if (GamePause == true)
{
}
RenderedImage = new DrawingImage(imageDrawings);
renderImage.Source = RenderedImage;
});
}
Could You explain me why second option of "Display()" method works fine, but the first one throwing exception? What I'am doing wrong?
Upvotes: 2
Views: 565
Reputation: 38087
Both the DrawingImage
and the DrawingGroup
inherit from DispatcherObject
, which means that they need to be accessed from the thread on which they were created. That is why your version where all of the work is invoked back to the dispatcher works correctly.
As pointed out by Brian Reichle, these object also inherit from System.Windows.Freezable
, which you can leverage to allow cross thread access to the objects.
Upvotes: 3