WPF 由于其他线程拥有此对象,因此调用线程无法对其进行访问
2015-04-22 18:44
246 查看
转自:
http://blog.sina.com.cn/s/blog_962250db0101487n.html
除非已经对WPF体系结构非常熟悉,对多线程开发很了解,不然我们在与WPF打交道的时候经常会遇到这样一个异常:
由于其他线程拥有此对象,因此调用线程无法对其进行访问。(The calling thread cannot access this object because a different thread owns it)
在WPF中,天生拥有两个线程,一个线程用于渲染UI,另一个线程是管理UI(这个我们称之为UI线程)。传说中android的动画效果为什么没有iphone的动画效果好,就是因为iphone的绘制渲染的线程的优先级非常高,只要有关于动画的操作,比如说滑动一个菜单,那么这个动画会被安排到最优先级运行,从而保证动画的流畅。这我没有深入研究,所以可能技术上来说以上描述不是十分正确,但可以按这个方式去理解。大概WPF中也是这样的理念。UI线程创建了那些在XAML或者在c#中定义的控件,并且拥有他们,并且出于对UI的保护,其他线程是不能访问到UI线程里的东西的,如果我们新建一个线程,然后在这个线程里面修改一个在xaml中或者在主线程中定义的Button.Content,那么就会得到这个异常。
在IM开发过程中,使用agsXMPP库的时候,agsXMPP有很多事件,比如XmppClientConnection.OnStateChanged事件,OnError事件等等,我们会用到很多事件处理函数,在这里必须注意一点就是,当这些事件被触发,代码被执行到事件处理函数里面的时候,执行代码的线程往往不是主线程(这里“往往”不知道用的对不对,反正我碰到的都不是在主线程中执行的),也就是说,如果这时在事件处理函数中写这样的代码:button1.content="something",就会抛出由于其他线程拥有此对象,因此调用线程无法对其进行访问异常。我们可以再visual
studio中调试代码时候在看到当前执行代码的是主线程还是其他线程:
如果线程一栏中没有写明是“主线程”,那么当前执行代码的线程就不是主线程。
这个时候,假如我们必须在其他线程中访问控件,怎么办?这就需要通过Dispatcher了。WPF中大多数控件都继承自DispatcherObject,也就拥有Dispatcher属性,这个Dispatatcher具体是什么东西,我就不写了,因为我也不知道,但显浅的来说,它是对他所属的线程进行工作调度的这么一个对象,或者说线程的一个管家,或者中介。你要在一个拥有某个控件的线程的外部(或者说其他线程)访问这个线程的控件,就只能通过这个控件的Dispatcher来处理了,Dispatcher有两个方法:Invoke和BeginInvoke,用来对外开放访问这个Dispatcher所属的线程所拥有的控件的机会。比如我想在其他线程中访问主线程的Button:
private
void OnEventFired(object sender, MouseButtonEventArgs e)
{
btn.Dispatcher.Invoke(new Action(delegate { button1.Content =
"some text"; }));
}
假设OnEventFired正被其他线程执行,代码里面通过btn.Dispatcher的Invoke方法执行一个(匿名的)函数,该函数里面是设置buttton1.content。
Invoke和BeginInvoke前者是即时调用和异步调用
http://blog.sina.com.cn/s/blog_962250db0101487n.html
除非已经对WPF体系结构非常熟悉,对多线程开发很了解,不然我们在与WPF打交道的时候经常会遇到这样一个异常:
由于其他线程拥有此对象,因此调用线程无法对其进行访问。(The calling thread cannot access this object because a different thread owns it)
在WPF中,天生拥有两个线程,一个线程用于渲染UI,另一个线程是管理UI(这个我们称之为UI线程)。传说中android的动画效果为什么没有iphone的动画效果好,就是因为iphone的绘制渲染的线程的优先级非常高,只要有关于动画的操作,比如说滑动一个菜单,那么这个动画会被安排到最优先级运行,从而保证动画的流畅。这我没有深入研究,所以可能技术上来说以上描述不是十分正确,但可以按这个方式去理解。大概WPF中也是这样的理念。UI线程创建了那些在XAML或者在c#中定义的控件,并且拥有他们,并且出于对UI的保护,其他线程是不能访问到UI线程里的东西的,如果我们新建一个线程,然后在这个线程里面修改一个在xaml中或者在主线程中定义的Button.Content,那么就会得到这个异常。
在IM开发过程中,使用agsXMPP库的时候,agsXMPP有很多事件,比如XmppClientConnection.OnStateChanged事件,OnError事件等等,我们会用到很多事件处理函数,在这里必须注意一点就是,当这些事件被触发,代码被执行到事件处理函数里面的时候,执行代码的线程往往不是主线程(这里“往往”不知道用的对不对,反正我碰到的都不是在主线程中执行的),也就是说,如果这时在事件处理函数中写这样的代码:button1.content="something",就会抛出由于其他线程拥有此对象,因此调用线程无法对其进行访问异常。我们可以再visual
studio中调试代码时候在看到当前执行代码的是主线程还是其他线程:
如果线程一栏中没有写明是“主线程”,那么当前执行代码的线程就不是主线程。
这个时候,假如我们必须在其他线程中访问控件,怎么办?这就需要通过Dispatcher了。WPF中大多数控件都继承自DispatcherObject,也就拥有Dispatcher属性,这个Dispatatcher具体是什么东西,我就不写了,因为我也不知道,但显浅的来说,它是对他所属的线程进行工作调度的这么一个对象,或者说线程的一个管家,或者中介。你要在一个拥有某个控件的线程的外部(或者说其他线程)访问这个线程的控件,就只能通过这个控件的Dispatcher来处理了,Dispatcher有两个方法:Invoke和BeginInvoke,用来对外开放访问这个Dispatcher所属的线程所拥有的控件的机会。比如我想在其他线程中访问主线程的Button:
private
void OnEventFired(object sender, MouseButtonEventArgs e)
{
btn.Dispatcher.Invoke(new Action(delegate { button1.Content =
"some text"; }));
}
假设OnEventFired正被其他线程执行,代码里面通过btn.Dispatcher的Invoke方法执行一个(匿名的)函数,该函数里面是设置buttton1.content。
Invoke和BeginInvoke前者是即时调用和异步调用
相关文章推荐
- wpf-由于其他线程拥有此对象,因此调用线程无法对其进行访问。
- 【黑马程序员】关于多线程聊天室中出现的“由于其他线程拥有此对象,因此调用线程无法对其进行访问”问题的探究
- 多线程BUG捕捉之:由于其他线程拥有此对象,因此调用线程无法对其进行访问
- Wpf 调用线程无法访问此对象,因为另一个线程拥有该对象,解决方案
- 调用线程无法访问此对象,因为另一个线程拥有该对象 [c# wpf定时器程序报的错误]
- WPF 调用线程无法访问此对象,因为另一个线程拥有该对象
- WPF调用线程 解决“调用线程无法访问此对象,因为另一个线程拥有该对象“问题
- WPF [调用线程无法访问此对象,因为另一个线程拥有该对象。] 解决方案
- WPF [调用线程无法访问此对象,因为另一个线程拥有该对象。] 解决方案以及如何实现字体颜色的渐变
- WPF中调用线程无法访问此对象,因为另一个线程拥有该对象 的解决方法
- WPF [调用线程无法访问此对象,因为另一个线程拥有该对象。] 解决方案
- WPF 出现“调用线程无法访问此对象,因为另一个线程拥有该对象”
- WPF异常:调用线程无法访问此对象,因为另一个线程拥有该对象。
- WPF调用线程 解决“调用线程无法访问此对象,因为另一个线程拥有该对象“问题
- WPF 委托刷新UI线程(System.InvalidOperationException: '调用线程无法访问此对象,因为另一个线程拥有该对象。')
- WPF [调用线程无法访问此对象,因为另一个线程拥有该对象。] 解决方案以及如何实现字体颜色的渐变
- 用了invoke还是出错的解决方法.wpf 调用线程无法访问此对象,因为另一个线程拥有该对象。
- WPF [调用线程无法访问此对象,因为另一个线程拥有该对象。] 解决方案以及如何实现字体颜色的渐变
- WPF 调用线程无法访问此对象,因为另一个线程拥有该对象
- WPF [调用线程无法访问此对象,因为另一个线程拥有该对象。] 解决方案以及如何实现字体颜色的渐变