因为不同的线程拥有it.WPF调用线程不能访问该对象因为不同的线程拥有it.WPF调用线程不能访问该

2019-05-16 15:04发布

每当我刷新一个标签,我得到这个错误: 因为不同的线程拥有它调用线程不能访问该对象。 我试图调用但它的失败。 我使用WPF形式。

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

Answer 1:

使用Dispatcher.Invoke方法。

同步执行的Dispatcher关联的线程上执行指定的委托。

在WPF中,只有线程创建DispatcherObject可以访问该对象。 例如,从主UI线程派生的后台线程不能更新在该UI线程上创建的按钮的内容 。 为了让后台线程能够访问Button的Content属性,后台线程必须与委托UI线程相关的工作给调度。 这是通过使用Invoke或BeginInvoke来完成。 调用是同步的而BeginInvoke是异步的。 该操作被添加到分派器的事件队列中在指定的DispatcherPriority。

你所得到的错误,因为是在UI线程创建的标签,你试图通过修改另一个线程的内容。 在这里,您将需要Dispatcher.Invoke。

看看这篇文章WPF线程构建更加适应应用与调度



Answer 2:

您可以使用调度此。 你的代码变得...

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


Answer 3:

使用Dispatcher.Invoke

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


Answer 4:

我开始一个非UI线程并且此线程内我盯着一个UI线程太多。 所以,我的要求是像非UI线程中运行的UI线程。 在处理这种情况下,我得到了以下异常。 “例外:调用线程不能因为不同的线程拥有它访问该对象。”

在这种情况下,我使用的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;
    }));                            
}


Answer 5:

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


Answer 6:

几点建议使用的BeginInvoke,但没有提到EndInvoke会的。 良好的做法是,“每一个的BeginInvoke有一个匹配的EndInvoke会”,当然需要有对抗的比赛条件有所保障(个人认为:与多个代码的BeginInvoke会发生什么,但没有完成处理了吗?)

人们很容易忘记,我已经看到了这个错误(是的,这错误的),在这两个例子MSDN和WinForms的书籍出版



文章来源: The calling thread cannot access this object because a different thread owns it.WPF