0

I am trying to make a warning window in an application. The window needs to run on a seperate thread and contains among other things a Canvas depicting a failing object. The Canvas already exists in the main application, and what i need is simply to show the same Canvas in the warning window. The problem is that i get an error saying that another thread owns the object. I tried doing a deep copy using this method but with no luck. Is there anything i missed, or is there really no simple method to copy a Canvas, or a collection of images. Alternatively, would it be possible to do the deep copy and then change the treading affinity of the copied object?

I should think that someone has encountered this problem before, but my serching skills have given me no relevant results this time.

Thanks in advance! -ruNury

EDIT 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;
    }
5
  • Only the thread that created a UI object (main) can access the UI object. Commented May 9, 2012 at 13:55
  • Yes, that is the reason why I need a COPY of the object which can be shown on the NEW thread... Commented May 9, 2012 at 14:13
  • I feel your pain. I have tried to do this and gave up. It seems that even a copy of a UI object still a UI object. I know this seems extreme but you may needs to serialize to string and create the canvas. I even had to serialize a FlowDocument to string to pass it from background to the main. Commented May 9, 2012 at 14:38
  • The annoying part is that I can put a break point in the dispatcher and see that testcanv contains the right data, but as soon as the im outside the dispatcher, testcanv children are owned by another thread... Commented May 10, 2012 at 8:08
  • Internally .NET only checks for ownership periodically. Commented May 10, 2012 at 12:01

1 Answer 1

0

You can singleton pattern to maintain one object of warning window.

When you want to put the canvas into warning window, you have to use Dispatcher.

Dispatcher will marshal method call onto UI thread.

something like

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

Where warningWindow will be available through singleton instance

Sign up to request clarification or add additional context in comments.

4 Comments

I updated the question (should have included the code from the beginning). What I did is more or less what u suggest, but testcanv is not accessible at the return point.
testcanv = CopyCanvas(t); --> it looks like the culprit.
Instead of testCanvas= CopyCanvas(t), can you put testCanvas into a Grid in XAML (say grid1), and assign it like grid1.Children.Add(testCanvas); stackoverflow.com/questions/311131/add-wpf-control-at-runtime
What will it help to put testcanv into a grid, when it is still not accessible in the warning window thread? As I see it the real problem is to have testcanv contain copies of the children in the 't' canvas...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.