2013-05-20 47 views
0

我很难理解为什么这个简单的方法不起作用 如果我理解正确,UIElements只能由他们自己的线程改变,后台线程不能。 试用此代码时。它抛出:WPF Dispatcher.BeginInvoke和线程访问

InvalidOperationException - 调用线程不能访问此对象,因为不同的线程拥有它。

代码以供参考:

 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(); 
+0

'System.Windows.Media.PointCollection'是一个'DependencyObject'。你不能在一个线程(后台线程)上实例化它,并在另一个线程(UI线程)上使用它。 –

+1

http://stackoverflow.com/questions/11923865/how-to-deal-with-cross-thread-access-exceptions –

回答

1

Polygon一个的UIElement。因此,它只能从创建它的线程访问。你在后台线程上创建它,所以它只能从该线程访问。当你试图从UI线程访问它时,它会对你大喊大叫。

您需要创建对象,对其进行修改并将其添加到您的容器中,全部在UI线程中。你刚刚展示的代码都不属于后台线程。

也许,如果你需要做的,而不是只使用4个硬编码值复杂的东西产生Point对象的序列,那么这将是可能属于在后台线程的唯一的一块。如果您需要查询数据库,或者执行一些昂贵的图形操作来确定点应该是什么,并且需要足够长的时间才能在UI线程中执行此操作,则需要在另一个线程中生成List<Point>的任务然后让UI线程获取这些点,将它们放入Polygon并将其添加到窗口中。