The calling thread cannot access this object because a different thread owns it.WPF

50,785

Solution 1

Use Dispatcher.Invoke Method.

Executes the specified delegate synchronously on the thread the Dispatcher is associated with.

Also

In WPF, only the thread that created a DispatcherObject may access that object. For example, a background thread that is spun off from the main UI thread cannot update the contents of a Button that was created on the UI thread. In order for the background thread to access the Content property of the Button, the background thread must delegate the work to the Dispatcher associated with the UI thread. This is accomplished by using either Invoke or BeginInvoke. Invoke is synchronous and BeginInvoke is asynchronous. The operation is added to the event queue of the Dispatcher at the specified DispatcherPriority.

You are getting the error because your label is created on UI thread and you are trying to modify its content via another thread. This is where you would require Dispatcher.Invoke.

Check out this article WPF Threads Build More Responsive Apps With The Dispatcher

Solution 2

You can use Dispatcher for this. Your code becomes...

private void imgPayment_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    Dispatcher.BeginInvoke(DispatcherPriority.Input, new ThreadStart(() =>
    {
        try
        {
            label1.Content = "df";
        }
        catch
        {
            lostfocs ld = new lostfocs(up);
          //  ld.Invoke("df");
            object obj=new object();
            ld.Invoke("sdaf");
        }
    }
));

Solution 3

use Dispatcher.Invoke

Example

    void modi()
    {
        if(!Dispatcher.CheckAccess())
        {
            Dispatcher.Invoke(
                    ()=>label1.Content = "df",DispatcherPriority.Normal);
        }
        else
        {
            label1.Content = "df";
        }
    }

Solution 4

I started one non-UI Thread and within this thread I stared one UI thread too. So my requirement is like running an UI thread within a non-UI thread. When handling this scenario I got the following exception. "Exception: The calling thread cannot access this object because a different thread owns it."

In this case I used the Dispatcher.Invoke method of the UI element as follows and it worked well.

if (m_contextWindow == null)
{   
    System.Threading.Thread newWindowThread = new System.Threading.Thread(new ThreadStart( () =>
    {
        // Create and show the Window
        m_contextWindow = new ContextWindow();
        m_contextWindow.DataContext = this;                            
        m_contextWindow.Show();
        // Start the Dispatcher Processing
        System.Windows.Threading.Dispatcher.Run();
    }));

    // Set the apartment state
    newWindowThread.SetApartmentState(ApartmentState.STA);
    // Make the thread a background thread
    newWindowThread.IsBackground = true;
    // Start the thread
    newWindowThread.Start();
}
else
{                     
    this.m_contextWindow.Dispatcher.Invoke(new ThreadStart(() => 
    {
        m_contextWindow.DataContext = this;
        if (m_contextWindow.Visibility == System.Windows.Visibility.Collapsed
         || m_contextWindow.Visibility == System.Windows.Visibility.Hidden)
            m_contextWindow.Visibility = System.Windows.Visibility.Visible;
    }));                            
}
Share:
50,785

Related videos on Youtube

Yasser
Author by

Yasser

student of Software Eng, 4th year. Interested in WPF

Updated on July 09, 2022

Comments

  • Yasser
    Yasser almost 2 years

    Whenever I refresh a label, I got this error: The calling thread cannot access this object because a different thread owns it. I tried to invoke but it's failed. I'm using WPF Form.

    delegate void lostfocs(string st);
       private void imgPayment_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
    
            Thread t = new Thread(modi);
            t.Start();
        }
     void modi()
        {
            try
            {
                label1.Content = "df";
            }
            catch
            {
                lostfocs ld = new lostfocs(up);
              //  ld.Invoke("df");
                object obj=new object();
                ld.Invoke("sdaf");
            }
        }
    void up(string st)
        {
            label1.Content = st;
        }
    
    • Tilak
      Tilak almost 12 years
      why are u using try catch block ?
  • brewmanz
    brewmanz over 9 years
    @Sinatr : Are you saying that it's ok to use BeginInvoke without EndInvoke? Or is it another part of my answer that's wrong? I've checked it and see no errors. Please explain why you made your comment "Obviously wrong answer"
  • Sinatr
    Sinatr over 9 years
    You've got comment in another your answer. In wpf Dispatcher doesn't have EndInvoke method.
  • Endareth
    Endareth about 9 years
    Thanks for including the Dispatcher.CheckAccess bit, this was the final step I was missing in a related issue!
  • Ievgen
    Ievgen about 8 years
    If someone searching for a problem with setting window owner from other thread: stackoverflow.com/questions/14896111/…