error:The calling thread cannot access this object because a different thread owns it解决方法

WPF 由于其他线程拥有此对象,因此调用线程无法对其进行访问。

 

一:WPF线程模型

除非已经对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前者是即时调用和异步调用

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这个错误通常在使用 `MySqlDataReader` 对象读取数据之前,尝试访问字段时出现。这是由于未调用 `Read()` 方法导致的。`Read()` 方法用于将 `MySqlDataReader` 定位到结果集中的下一行数据,并返回一个布尔值表示是否还有更多的行可供读取。 为了解决这个错误,确保在尝试访问字段之前调用了 `Read()` 方法。以下是一个示例代码片段,演示了正确使用 `MySqlDataReader` 的方式: ```vb Using conn As New MySqlConnection(connectionString) conn.Open() Dim sql As String = "SELECT * FROM yourTableName" Using cmd As New MySqlCommand(sql, conn) Using reader As MySqlDataReader = cmd.ExecuteReader() While reader.Read() ' 在每次循环中,都会将 reader 定位到结果集中的下一行数据 ' 然后可以通过 reader 对象访问字段 ' 例如,访问名为 "columnName" 的字段: Dim value As String = reader("columnName").ToString() ' 处理读取到的数据... End While End Using End Using conn.Close() End Using ``` 在上述代码中,我们在每次循环开始之前调用 `reader.Read()` 方法来定位到下一行数据。然后,我们可以通过 `reader` 对象访问具体的字段,并进行相关处理。 请注意,确保将 `yourTableName` 替换为你要从中读取数据的表名。另外,请根据需要调整代码以适应你的实际情况。 如果你仍然遇到问题,请提供更多的代码和错误信息,以便更好地帮助你解决问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值