WPF Dispatcher.BeginInvoke 和线程访问
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16657211/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF Dispatcher.BeginInvoke and thread access
提问by EdQ3
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:
我很难理解为什么这个简单的方法不起作用如果我理解正确,UIElements 只能由它们自己的线程更改,而后台线程不能。尝试此代码时。它抛出:
InvalidOperationException - The calling thread cannot access this object because a different thread owns it.
InvalidOperationException - 调用线程无法访问此对象,因为其他线程拥有它。
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();
回答by Servy
Polygonisa 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.
Polygon是一个 UIElement。因此,它只能从创建它的线程访问。您在后台线程上创建它,因此只能从该线程访问它。当您尝试从 UI 线程访问它时,它会对您大喊大叫。
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.
您需要在 UI 线程中创建对象、修改它并将其添加到您的容器中。您刚刚展示的代码都不属于后台线程。
Perhaps, if you needed to do something complex to generate the sequence of Pointobjects, instead of just using 4 hard coded values, then that would be the only piece that maybelong 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 Polygonand add that to the window.
也许,如果您需要做一些复杂的事情来生成Point对象序列,而不是仅使用 4 个硬编码值,那么这将是唯一可能属于后台线程的部分。如果你需要查询一个数据库,或者做一些昂贵的图形操作来确定点应该是什么,并且花费的时间足够长以至于你不能在 UI 线程中完成,那么有一个任务List<Point>在另一个线程中生成一个然后让 UI 线程获取这些点,将它们放入 aPolygon并将其添加到窗口中。

