Reputation: 31
I'm having difficulty understanding why this simple method isn't working If I understand correctly, UIElements must be changed only by their own thread, and background threads cannot. When trying this code. it throws:
InvalidOperationException - The calling thread cannot access this object because a different thread owns it.
Code for reference:
Canvas c = new Canvas();
RootWindow.AddChild(c);
Thread r = new Thread( new ThreadStart(() =>
{
Polygon p = new Polygon();
PointCollection pC = new PointCollection();
pC.Add(new Point(1.5, 4.5));
pC.Add(new Point(-7, 9));
pC.Add(new Point(1.5, -5));
pC.Add(new Point(10, 9));
p.Points = pC;
p.Stroke = Brushes.Black;
p.Fill = Brushes.Green;
c.Dispatcher.BeginInvoke( DispatcherPriority.Normal , new Action( () => { c.Children.Add(p); } ));
}));
r.SetApartmentState(ApartmentState.STA);
r.Start();
Upvotes: 0
Views: 5285
Reputation: 203820
Polygon
is a UIElement. As such, it can only ever be accessed from the thread that created it. You created it on a background thread, so it can only ever be accessed from that thread. When you tried to access it from the UI thread it yells at you.
You need to create the object, modify it, and add it to your container, all in the UI thread. None of the code that you've just shown belongs in a background thread.
Perhaps, if you needed to do something complex to generate the sequence of Point
objects, instead of just using 4 hard coded values, then that would be the only piece that may belong in a background thread. If you need to query a database, or do some expensive graphical operation to determine what the points should be, and it takes long enough that you can't do it in the UI thread, then have a task that generates a List<Point>
in another thread and then let the UI thread take those points, put them into a Polygon
and add that to the window.
Upvotes: 1