BeginInvoke 方法真的是新开一个线程进行异步调用吗?
转自原文BeginInvoke 方法真的是新开一个线程进行异步调用吗?
BeginInvoke 方法真的是新开一个线程进行异步调用吗?
参考以下代码:
public delegate void treeinvoke();
private void UpdateTreeView()
{
MessageBox.Show(System.Threading.Thread.CurrentThread.Name);
}
private void button1_Click(object sender, System.EventArgs e)
{
System.Threading.Thread.CurrentThread.Name = "UIThread";
treeView1.BeginInvoke(new treeinvoke(UpdateTreeView));
}
看看运行结果,弹出的对话框中显示的是 UIThread,这说明 BeginInvoke 所调用的委托根本就是在 UI 线程中执行的。
既然是在 UI 线程中执行,又何来“异步执行”一说呢?
我们再看看下面的代码:
public delegate void treeinvoke();
private void UpdateTreeView()
{
MessageBox.Show(Thread.CurrentThread.Name);
}
private void button1_Click(object sender, System.EventArgs e)
{
Thread.CurrentThread.Name = "UIThread";
Thread th = new Thread(new ThreadStart(StartThread));
th.Start();
}
private void StartThread()
{
Thread.CurrentThread.Name = "Work Thread";
treeView1.BeginInvoke(new treeinvoke(UpdateTreeView));
}
再看看运行结果,弹出的对话框中显示的还是 UIThread,这说明什么?这说明 UI控件发起的 BeginInvoke 方法所调用的委托无论如何都是在 UI 线程中执行的(这话话的原始语句有待商讨,因为你是用treeView1去BeginInvoke的,可将前面的句子加上如上限定词“ UI控件发起的”。转载者备注)。
那 BeginInvoke 究竟有什么用呢?
在多线程编程中,我们经常要在工作线程中去更新界面显示,而在多线程中直接调用界面控件的方法是错误的做法,具体的原因可以在看完我的这篇之后看看
这篇:在多线程中如何调用Winform,如果你是大牛的话就不要看我这篇了,直接看那篇吧,反正那篇文章我没怎么看懂。
Invoke 和 BeginInvoke 就是为了解决这个问题而出现的,使你在多线程中安全的更新界面显示。
正确的做法是: 将工作线程中涉及更新界面的代码封装为一个方法,通过 Invoke 或者 BeginInvoke 去调用,两者的区别就是一个导致工作线程等待,而另外一个则不会。
而所谓的“一面响应操作,一面添加节点”永远只能是相对的,使 UI 线程的负担不至于太大而以,因为界面的正确更新始终要通过 UI 线程去做,
我们要做的事情是在工作线程中包揽大部分的运算,而将对纯粹的界面更新放到 UI 线程中去做,这样也就达到了减轻 UI 线程负担的目的了。
而在那段更新树节点的代码中,其实唯一起作用的代码是:System.Threading.Thread.Sleep(100);,它使 UI 线程有了处理界面消息的机会,
其实 数码幽灵 将问题复杂化了,只要以下的代码就可以很好的工作了。
private void button1_Click_(object sender, System.EventArgs e)
{
TreeNode tn;
for(int i=;i<;i++)
{
tn=new TreeNode (i.ToString());
this.treeView1.Nodes[].Nodes.Add(tn);
if (i% == ) Application.DoEvents();
}
}
BeginInvoke 方法真的是新开一个线程进行异步调用吗?的更多相关文章
- java的服务是每收到一个请求就新开一个线程来处理吗?tomcat呢?
首先,服务器的实现不止有这两种方式. 先谈谈题主说的这两种服务器模型: 1.收到一个请求就处理,这个时候就不能处理新的请求,这种为阻塞 这个是单线程模型,无法并发,一个请求没处理完服务器就会阻塞,不会 ...
- WinForm中新开一个线程操作 窗体上的控件(跨线程操作控件)
最近在做一个winform的小软件(抢票的...).登录窗体要从远程web页面获取一些数据,为了不阻塞登录窗体的显示,开了一个线程去加载数据远程的数据,会报一个错误"线程间操作无效: 从不是 ...
- C#新开一个线程取到数据,如何更新到主线程UI上面
一:问题 之前有被面试官问过,在WinForm中,要去网络上获取数据,由于网络环境等原因,不能很快的完成,因此会发生进程阻塞,造成主进程假死的现象,需要怎么解决? 二:思路 因此,往往是新 ...
- java future模式 所线程实现异步调用(转载
java future模式 所线程实现异步调用(转载) 在多线程交互的中2,经常有一个线程需要得到另个一线程的计算结果,我们常用的是Future异步模式来加以解决.Future顾名思意,有点像期货市场 ...
- java中最简单的方式新起一个线程
启动一个线程在一个方法中启动一个线程,有两种方法第一种是让类实现Runable接口,这样的话编译器就会提示你实现里面的未实现的方法(就是run方法)第二种是,现在方法中new一个线程,然后直接调用他的 ...
- Python+Selenium练习篇之15-在浏览器中新开一个tab
本文介绍如selenium方法打开一个新的tab,我们知道在浏览器里,我们按住 ctrl+ t 就可以新打开一个tab.所以我们学习如何利用webdriver中send_key 的方法去触发ctrl+ ...
- Java里一个线程两次调用start()方法会出现什么情况
Java的线程是不允许启动两次的,第二次调用必然会抛出IllegalThreadStateException,这是一种运行时异常,多次调用start被认为是编程错误. 如果业务需要线程run中的代码再 ...
- C# 线程池异步调用
许多应用程序使用多个线程,但这些线程经常在休眠状态中耗费大量的时间来等待事件发生.其他线程可能进入休眠状态,并且仅定期被唤醒以轮询更改或更新状态信息,然后再次进入休眠状态.为了简化对这些线程的管理,. ...
- android为什么不允许新开启一个线程来更新UI,而是用handler来更新界面
下面是快速创建一个新线程的方法: 第一种:直接创建子线程并启动 new Thread() {@Overridepublic void run() { //这里写入子线程需要做的工作 ...
随机推荐
- python2 使用matplotlib
背景 由於pyh在python3上沒法兒用,所以只能在python2上用pyh2 相應地也要在python2上使用matplotlib 下載 有兩種方法,pip & dnf pip爲: pip ...
- Encode Adjacent Letters
Encode a string by counting the consecutive letter. (i.e., "aaaabbxxxyyz" might become &qu ...
- org.hibernate.hql.QueryExecutionRequestException:org.hibernate.hql.QueryExecutionRequestException: Not supported for DML operations【异常】
springData学习资料 [http://blog.csdn.net/lw_power/article/details/51296353] [JPA报错]org.springframework.w ...
- javascript进阶修炼之二——DOM,事件及定时器
获得DOM元素的引用 首先注意以下几点: 注意document.getElementById,任何依赖于这个方法的代码都会成为IE怪异行为的牺牲品.因为在IE中,这个方法也会通过name属性来寻找 ...
- P2P UPD打洞原理
转自:http://blog.pfan.cn/fengfei/18828.html 首先先介绍一些基本概念: NAT(Network Address Tr ...
- JavaScript模块化-require.js,r.js和打包发布
在JavaScript模块化和闭包和JavaScript-Module-Pattern-In-Depth这两篇文章中,提到了模块化的基本思想,但是在实际项目中模块化和项目人员的分工,组建化开发,打包发 ...
- Python——深浅Copy
1. 赋值 赋值:指向同一块内存地址,所以同时改变 l1 = [1,2,3] l2 = l1 l1.append('a') print(l1,l2) # [1, 2, 3, 'a'] [1, 2, 3 ...
- wdlinux重新编译nginx
背景: 由于web站点需要换主机,并且切换环境. 站点需要做反相代理(nginx),主机从美国迁移到香港[考虑到速度问题,为什么不用大陆阿里云ECS服务器?几十个域名备案麻烦,还有阿里云内地没有多ip ...
- 在Mac OS上搭建Python的开发环境
本文转载自:http://www.jb51.net/article/76931.htm 一. 安装python mac系统其实自带了一个python的执行执行环境,用来运行python还行,但是开发可 ...
- ora-01658: 无法为表空间*****中的段创建 INITIAL 区
ora-01658: 无法为表空间*****中的段创建 INITIAL 区 原因:表空间不足 增大表空间.如果表空间动态增长,则扩大表空间的最大值.