首页 文章

调用线程无法访问此对象,因为另一个线程拥有它.WPF

提问于
浏览
22

每当我刷新标签时,我都会收到此错误: The calling thread cannot access this object because a different thread owns it. 我尝试使用WPF表单调用但是它是's failed. I' m .

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

6 回答

  • 1

    使用Dispatcher.Invoke方法 .

    在与Dispatcher关联的线程上同步执行指定的委托 .

    在WPF中,只有创建DispatcherObject的线程才能访问该对象 . 例如,从主UI线程分离出来的后台线程无法更新在UI线程上创建的Button的内容 . 为了让后台线程访问Button的Content属性,后台线程必须将工作委托给与UI线程关联的Dispatcher . 这是通过使用Invoke或BeginInvoke来完成的 . Invoke是同步的,BeginInvoke是异步的 . 该操作将添加到指定DispatcherPriority的Dispatcher的事件队列中 .

    您收到错误是因为您的标签是在UI线程上创建的,并且您正在尝试通过另一个线程修改其内容 . 这是您需要Dispatcher.Invoke的地方 .

    看看这篇文章WPF Threads Build More Responsive Apps With The Dispatcher

  • 11

    您可以使用Dispatcher . 你的代码变成......

    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");
            }
        }
    ));
    
  • 0

    使用Dispatcher.Invoke

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

    我启动了一个非UI线程,在这个线程中我也盯着一个UI线程 . 所以我的要求就像在非UI线程中运行UI线程 . 处理此方案时,我得到以下异常 . "Exception: The calling thread cannot access this object because a different thread owns it."

    在这种情况下,我使用了UI元素的Dispatcher.Invoke方法,如下所示,它运行良好 .

    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;
        }));                            
    }
    
  • 16
    private void imgPayment_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            {
                Dispatcher.BeginInvoke(DispatcherPriority.Input, new ThreadStart(() =>
                {
                    try
                    {
                        label1.Content = "df";
                    }
                    catch
                    {
                        lostfocs ld = new lostfocs(up);
                        object obj = new object();
                        ld.Invoke("sdaf");
                    }
                }));
            }
    
  • 40

    有几个使用BeginInvoke的建议,但没有提到EndInvoke . 好的做法是'每个BeginInvoke都有一个匹配的EndInvoke',当然还需要有一些防范竞争条件的保护措施(想想:多个BeginInvoke代码会发生什么,但是还没有完成处理?)

    它已经在MSDN示例和WinForms上发布的书籍中看到了这个错误(并且,是的,这是一个错误)

相关问题