【问题标题】:How to use a copy (or same) object in multiple threads如何在多个线程中使用副本(或相同)对象
【发布时间】:2012-05-18 01:11:09
【问题描述】:

我正在尝试在应用程序中创建一个警告窗口。该窗口需要在单独的线程上运行,并且除其他外还包含一个描绘失败对象的画布。 Canvas 已经存在于主应用程序中,我需要的只是在警告窗口中显示相同的 Canvas。问题是我收到一个错误,说另一个线程拥有该对象。 我尝试使用this 方法进行深层复制,但没有运气。有什么我错过的吗,或者真的没有简单的方法来复制画布或图像集合。或者,是否可以进行深层复制,然后更改复制对象的踏步亲和性?

我应该认为以前有人遇到过这个问题,但是我的搜索技能这次没有给我相关的结果。

提前致谢! -ruNury

编辑 1

    private Canvas cloneCanvas()
    {
        Canvas testcanv = new Canvas();

        Dispatcher.Invoke(new Action(delegate
        {
            var t = SomeViewModel.GetCanvasWithImages();
            testcanv = CopyCanvas(t);
        }));

        return testcanv;
    }

    public static UIElement DeepCopy(UIElement element)
    {
        if (element != null)
        {
            var xaml = XamlWriter.Save(element);

            var xamlString = new StringReader(xaml);

            var xmlTextReader = new XmlTextReader(xamlString);

            var deepCopyObject = (UIElement)XamlReader.Load(xmlTextReader);

            return deepCopyObject;
        }

        return null;

    }

    private Canvas CopyCanvas(Canvas inputCanvas)
    {

        if (inputCanvas != null)
        {
            var outputCanvas = new Canvas();

            foreach (UIElement child in inputCanvas.Children)
            {
                outputCanvas.Children.Add(DeepCopy(child));
            }

            return outputCanvas;
        }

        return null;
    }

【问题讨论】:

  • 只有创建UI对象的线程(main)才能访问UI对象。
  • 是的,这就是为什么我需要可以在新线程上显示的对象的副本...
  • 我感受到你的痛苦。我试图这样做并放弃了。似乎即使是 UI 对象的副本仍然是 UI 对象。我知道这看起来很极端,但您可能需要序列化为字符串并创建画布。我什至不得不将 FlowDocument 序列化为字符串以将其从后台传递到主目录。
  • 烦人的部分是我可以在调度程序中放置一个断点并查看 testcanv 包含正确的数据,但是一旦我在调度程序之外,testcanv 子级就属于另一个线程。 .
  • 内部 .NET 只定期检查所有权。

标签: c# wpf canvas copy clone


【解决方案1】:

您可以单例模式来维护一个警告窗口对象。

当你想将画布放入警告窗口时,你必须使用Dispatcher

Dispatcher 会将方法调用编组到 UI 线程。

类似

  warningWindow.Dispatcher.Invoke(
      System.Windows.Threading.DispatcherPriority.Normal,
      new Action(
        delegate()
        {
          myCheckBox.IsChecked = true;
        }
    ));

warningWindow 将通过单例实例获得

【讨论】:

  • 我更新了问题(应该从一开始就包含代码)。我所做的或多或少是您的建议,但在返回点无法访问 testcanv。
  • testcanv = CopyCanvas(t); --> 看起来像是罪魁祸首。
  • 代替 testCanvas= CopyCanvas(t),你能不能把 testCanvas 放到 XAML 中的一个 Grid 中(比如 grid1),然后像 grid1.Children.Add(testCanvas); stackoverflow.com/questions/311131/add-wpf-control-at-runtime
  • 当在警告窗口线程中仍然无法访问 testcanv 时,将它放入网格有什么帮助?在我看来,真正的问题是让 testcanv 在“t”画布中包含孩子的副本......
猜你喜欢
  • 2014-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-31
  • 2016-04-18
  • 1970-01-01
相关资源
最近更新 更多