首页新闻找找看学习计划

委托的一点疑惑。为何此处仍然报线程不安全的异常【图】

0
悬赏园豆:15 [已解决问题] 解决于 2017-02-27 15:20

我对委托的理解是一个函数指针,将某个方法的指针交给一个委托,然后由委托根据指针找到创建方法的线程去安全的调用方法。

疑问1:异步委托是否新开线程了。

疑问2:

当用子线程更新主线程控件状态时考虑到线程安全性一般都这样做。

1 ***某线程的方法里***
2 
3 this.Invoke(New Action(()=>{
4      lable1.Text="111";
5         }));
6 
7 ***某线程的方法里***

 

在winform里,按钮控件的点击事件是属于主线程的。所以效果都是同步的。因此当触发按钮的点击事件执行button1_click时并没有跨线程。所以更新控件直接赋值即可,不必用Invoke方式(按钮事件也是个委托,此处暂且不考虑委托对线程安全起到的作用,因为根本没跨线程)。

而在winform里,BackGroundWorker这个控件执行时就是跨线程的了,他会异步的执行操作,在操作完成时触发RunWorkerCompleted事件。使用时只要注册RunWorkerCompleted事件,在这个事件触发我的方法时直接给控件赋值即可,也不必用Invoke考虑线程安全性。这里我有点疑惑。之所以不必用Invoke,是否就是RunWorkerCompleted这个事件(也是个委托),以线程安全的方式调用的我的方法,所以不必在我的方法里用Invoke。

如果是,那为什么我自定义的这个情况就出错了。

我的事件触发定义的方法后,为什么就不是线程安全了?

雄风哥的主页 雄风哥 | 初学一级 | 园豆:55
提问于:2015-04-14 16:45
< >
分享
最佳答案
0

你把 Control.Invoke 同 Delegate.Invoke(BeginInvoke) 的作用搞混淆了,它们不是一个路数的。

收获园豆:15
Launcher | 高人七级 |园豆:45040 | 2015-04-14 17:30
其他回答(2)
0

因为创建你窗体上控件的是主线程,但是你当前调用的方法是用另一个线程来调用,因此会报异常。

lblLoopTimes.Invoke(new Action(()=>{lblLoopTimes.Text=_loopTimes.ToString()}));

对于多线程必须用invoke方法

virtual1988 | 园豆:252 (菜鸟二级) | 2015-04-14 17:22

可是方法也是通过事件触发调用的啊,委托调用是线程安全的啊。BackgroundWorker也会异步执行啊。为什么他的完成事件里就可以不用Invoke的方式?

另外问个问题。lblLoopTimes.Invoke(...) 和 主线程this.Invoke是一样的吧? 都是主线程去Invoke

支持(0) 反对(0) 雄风哥 | 园豆:55 (初学一级) | 2015-04-14 17:30
0

 Control.Invoke 同 Delegate.Invoke(BeginInvoke) 这是两个概念

茂茂 | 园豆:2860 (老鸟四级) | 2015-04-15 09:53
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册