调用线程无法访问此对象,因为另一个线程拥有它.WPF
每当我刷新标签时,我都会收到此错误: 调用线程无法访问此对象,因为另一个线程拥有它。 我试图调用,但它失败了。 我正在使用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; }
使用Dispatcher.Invoke方法。
在与Dispatcher关联的线程上同步执行指定的委托。
也
在WPF中,只有创建DispatcherObject的线程才能访问该对象。 例如, 从主UI线程分离出来的后台线程无法更新在UI线程上创建的Button的内容 。 为了让后台线程访问Button的Content属性,后台线程必须将工作委托给与UI线程关联的Dispatcher。 这是通过使用Invoke或BeginInvoke来完成的。 Invoke是同步的,BeginInvoke是异步的。 该操作将添加到指定DispatcherPriority的Dispatcher的事件队列中。
您收到错误是因为您的标签是在UI线程上创建的,并且您正在尝试通过另一个线程修改其内容。 这是您需要Dispatcher.Invoke的地方。
看看这篇文章WPF Threads使用Dispatcher构建更多响应式应用程序
您可以使用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"); } } ));
使用Dispatcher.Invoke
例
void modi() { if(!Dispatcher.CheckAccess()) { Dispatcher.Invoke( ()=>label1.Content = "df",DispatcherPriority.Normal); } else { label1.Content = "df"; } }
我启动了一个非UI线程,在这个线程中我也盯着一个UI线程。 所以我的要求就像在非UI线程中运行UI线程。 处理此方案时,我得到以下exception。 “exception:调用线程无法访问此对象,因为不同的线程拥有它。”
在这种情况下,我使用了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; })); }
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"); } })); }
有几个使用BeginInvoke的建议,但没有提到EndInvoke。 好的做法是’每个BeginInvoke都有一个匹配的EndInvoke’,当然需要有一些防范竞争条件的保护(想想:多个BeginInvoke代码会发生什么,但是还没有完成处理?)
它很容易忘记,我在MSDN示例和WinForms上发布的书籍中都看到了这个错误(是的,这是一个错误)