【问题标题】:WPF Dispatcher.BeginInvoke and thread accessWPF Dispatcher.BeginInvoke 和线程访问
【发布时间】:2013-05-20 19:48:34
【问题描述】:

我很难理解为什么这个简单的方法不起作用 如果我理解正确,UIElements 必须只能由它们自己的线程更改,而后台线程不能。 尝试此代码时。它抛出:

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

【问题讨论】:

  • System.Windows.Media.PointCollectionDependencyObject。您不能在一个线程(后台线程)上实例化它并在另一个线程(UI 线程)上使用它。

标签: c# wpf dispatcher


【解决方案1】:

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

您需要在 UI 线程中创建、修改对象并将其添加到容器中。您刚刚显示的代码都不属于后台线程。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多