0
votes

I am trying to display a menu element in my application as soon as a specific bluetooth message arrives. The messages are collected and interpreted through a timer method and if the correct message arrives, the element should be rendered visible. I keep getting an exception telling me that the object is owned by another thread and cannot be accessed.

// Shows a TangibleMenu element
private void Show(TangibleMenu TangibleMenuElement)
{
    if (TangibleMenuElement.Shape.CheckAccess())
    {
        Debug.WriteLine("normal show");
        TangibleMenuElement.Shape.Opacity = 1;
        TangibleMenuElement.Shape.Visibility = System.Windows.Visibility.Visible;
        this.ParentContainer.Activate(TangibleMenuElement.Shape);
    }
    else
    {
        Dispatcher.CurrentDispatcher.Invoke(new Action(() =>
        {
            Debug.WriteLine("dispatcher show");
            TangibleMenuElement.Shape.Opacity = 1; // EXCEPTION HERE
            TangibleMenuElement.Shape.Visibility = System.Windows.Visibility.Visible;
            this.ParentContainer.Activate(TangibleMenuElement.Shape);
        }));
    }
}

I thought that this exact issue could be solved by using the Dispatcher but in this case, it doesn't seem to work. TangibleMenuElement.Shape is a ScatterViewItem from the Microsoft Surface SDK. Does anyone have any suggestions?

3
is the Dispatcher thread the one that created the TangibleMenuElementsa_ddam213
No, I want to change some properties of the already and by another thread created object. How do I do that?xmashallax

3 Answers

0
votes

TangibleMenuElement needs to be created on the UI thread, not just added to the container on the UI thread. This means you'll need to construct the FrameworkElement completely on the UI thread.

0
votes

Solution to my problem: I accessed the wrong Dispatcher ...

I did not pay attention to the difference between Dispatcher.CurrentDispatcher and Application.Current.Dispatcher. The first one returns the dispatcher for the current thread, the second one returns the UI thread in my case (first thread of the application).

So my Timer thread got the message, called Show(), asked for a Dispatcher and got one ... but it was the Dispatcher of the Timer thread and not the UI thread. When I changed the code to Application.Current.Dispatcher it worked as expected.

A more detailled explanation can be found here.

0
votes

try this

// Shows a TangibleMenu element
private void Show(TangibleMenu TangibleMenuElement)
{
    App.Current.Dispatcher.Invoke(new Action(() =>
    {
        if (TangibleMenuElement.Shape.CheckAccess())
        {
            Debug.WriteLine("normal show");
            TangibleMenuElement.Shape.Opacity = 1;
            TangibleMenuElement.Shape.Visibility = System.Windows.Visibility.Visible;
            this.ParentContainer.Activate(TangibleMenuElement.Shape);
        }
        else
        {
            Debug.WriteLine("dispatcher show");
            TangibleMenuElement.Shape.Opacity = 1; // EXCEPTION HERE
            TangibleMenuElement.Shape.Visibility = System.Windows.Visibility.Visible;
            this.ParentContainer.Activate(TangibleMenuElement.Shape);
        }
    }));
}