C# 如何在多个线程中使用副本(或相同)对象

C# 如何在多个线程中使用副本(或相同)对象,c#,wpf,canvas,copy,clone,C#,Wpf,Canvas,Copy,Clone,我试图在应用程序中创建一个警告窗口。该窗口需要在一个单独的线程上运行,并包含一个描绘失败对象的画布。画布已经存在于主应用程序中,我需要的只是在警告窗口中显示相同的画布。问题是我得到一个错误,说另一个线程拥有这个对象。 我试着用这种方法做一个深度复制,但没有成功。是否有我遗漏的东西,或者是否真的没有复制画布或图像集合的简单方法。或者,是否可以进行深度复制,然后更改复制对象的踩踏亲和性 我应该认为以前有人遇到过这个问题,但我的服务技能这次没有给我带来任何相关的结果 提前谢谢! -破烂的 编辑1

我试图在应用程序中创建一个警告窗口。该窗口需要在一个单独的线程上运行,并包含一个描绘失败对象的画布。画布已经存在于主应用程序中,我需要的只是在警告窗口中显示相同的画布。问题是我得到一个错误,说另一个线程拥有这个对象。 我试着用这种方法做一个深度复制,但没有成功。是否有我遗漏的东西,或者是否真的没有复制画布或图像集合的简单方法。或者,是否可以进行深度复制,然后更改复制对象的踩踏亲和性

我应该认为以前有人遇到过这个问题,但我的服务技能这次没有给我带来任何相关的结果

提前谢谢! -破烂的

编辑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;
    }

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

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

Dispatcher将封送方法调用到UI线程

差不多

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

当warningWindow通过singleton实例可用时

只有创建UI对象(主)的线程才能访问UI对象。是的,这就是我需要对象副本的原因,该副本可以显示在新线程上……我感到您的痛苦。我试着这么做,但还是放弃了。看起来,即使是UI对象的副本也仍然是UI对象。我知道这似乎有些极端,但您可能需要序列化字符串并创建画布。我甚至不得不将一个FlowDocument序列化为字符串,以便将其从后台传递到main。令人恼火的是,我可以在dispatcher中放置一个断点,并查看testcanv是否包含正确的数据,但只要im在dispatcher之外,testcanv子线程由另一个线程拥有…内部.NET只定期检查所有权。我更新了问题(应该从一开始就包含代码)。我所做的或多或少是您所建议的,但是在返回点无法访问testcanv。testcanv=CopyCanvas(t);-->它看起来像是罪魁祸首。您可以将testCanvas放在XAML中的网格中(比如grid1)而不是testCanvas=CopyCanvas(t),并像grid1.Children.Add(testCanvas)那样分配它吗;当在警告窗口线程中仍然无法访问testcanv时,将其放入网格有什么帮助?在我看来,真正的问题是让testcanv在“t”画布中包含子级的副本。。。