转自原文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 方法真的是新开一个线程进行异步调用吗?的更多相关文章

  1. java的服务是每收到一个请求就新开一个线程来处理吗?tomcat呢?

    首先,服务器的实现不止有这两种方式. 先谈谈题主说的这两种服务器模型: 1.收到一个请求就处理,这个时候就不能处理新的请求,这种为阻塞 这个是单线程模型,无法并发,一个请求没处理完服务器就会阻塞,不会 ...

  2. WinForm中新开一个线程操作 窗体上的控件(跨线程操作控件)

    最近在做一个winform的小软件(抢票的...).登录窗体要从远程web页面获取一些数据,为了不阻塞登录窗体的显示,开了一个线程去加载数据远程的数据,会报一个错误"线程间操作无效: 从不是 ...

  3. C#新开一个线程取到数据,如何更新到主线程UI上面

       一:问题 之前有被面试官问过,在WinForm中,要去网络上获取数据,由于网络环境等原因,不能很快的完成,因此会发生进程阻塞,造成主进程假死的现象,需要怎么解决?    二:思路 因此,往往是新 ...

  4. java future模式 所线程实现异步调用(转载

    java future模式 所线程实现异步调用(转载) 在多线程交互的中2,经常有一个线程需要得到另个一线程的计算结果,我们常用的是Future异步模式来加以解决.Future顾名思意,有点像期货市场 ...

  5. java中最简单的方式新起一个线程

    启动一个线程在一个方法中启动一个线程,有两种方法第一种是让类实现Runable接口,这样的话编译器就会提示你实现里面的未实现的方法(就是run方法)第二种是,现在方法中new一个线程,然后直接调用他的 ...

  6. Python+Selenium练习篇之15-在浏览器中新开一个tab

    本文介绍如selenium方法打开一个新的tab,我们知道在浏览器里,我们按住 ctrl+ t 就可以新打开一个tab.所以我们学习如何利用webdriver中send_key 的方法去触发ctrl+ ...

  7. Java里一个线程两次调用start()方法会出现什么情况

    Java的线程是不允许启动两次的,第二次调用必然会抛出IllegalThreadStateException,这是一种运行时异常,多次调用start被认为是编程错误. 如果业务需要线程run中的代码再 ...

  8. C# 线程池异步调用

    许多应用程序使用多个线程,但这些线程经常在休眠状态中耗费大量的时间来等待事件发生.其他线程可能进入休眠状态,并且仅定期被唤醒以轮询更改或更新状态信息,然后再次进入休眠状态.为了简化对这些线程的管理,. ...

  9. android为什么不允许新开启一个线程来更新UI,而是用handler来更新界面

    下面是快速创建一个新线程的方法: 第一种:直接创建子线程并启动      new Thread() {@Overridepublic void run() {     //这里写入子线程需要做的工作  ...

随机推荐

  1. python2 使用matplotlib

    背景 由於pyh在python3上沒法兒用,所以只能在python2上用pyh2 相應地也要在python2上使用matplotlib 下載 有兩種方法,pip & dnf pip爲: pip ...

  2. Encode Adjacent Letters

    Encode a string by counting the consecutive letter. (i.e., "aaaabbxxxyyz" might become &qu ...

  3. 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 ...

  4. javascript进阶修炼之二——DOM,事件及定时器

    获得DOM元素的引用 首先注意以下几点:   注意document.getElementById,任何依赖于这个方法的代码都会成为IE怪异行为的牺牲品.因为在IE中,这个方法也会通过name属性来寻找 ...

  5. P2P UPD打洞原理

    转自:http://blog.pfan.cn/fengfei/18828.html 首先先介绍一些基本概念:            NAT(Network Address             Tr ...

  6. JavaScript模块化-require.js,r.js和打包发布

    在JavaScript模块化和闭包和JavaScript-Module-Pattern-In-Depth这两篇文章中,提到了模块化的基本思想,但是在实际项目中模块化和项目人员的分工,组建化开发,打包发 ...

  7. Python——深浅Copy

    1. 赋值 赋值:指向同一块内存地址,所以同时改变 l1 = [1,2,3] l2 = l1 l1.append('a') print(l1,l2) # [1, 2, 3, 'a'] [1, 2, 3 ...

  8. wdlinux重新编译nginx

    背景: 由于web站点需要换主机,并且切换环境. 站点需要做反相代理(nginx),主机从美国迁移到香港[考虑到速度问题,为什么不用大陆阿里云ECS服务器?几十个域名备案麻烦,还有阿里云内地没有多ip ...

  9. 在Mac OS上搭建Python的开发环境

    本文转载自:http://www.jb51.net/article/76931.htm 一. 安装python mac系统其实自带了一个python的执行执行环境,用来运行python还行,但是开发可 ...

  10. ora-01658: 无法为表空间*****中的段创建 INITIAL 区

    ora-01658: 无法为表空间*****中的段创建 INITIAL 区 原因:表空间不足 增大表空间.如果表空间动态增长,则扩大表空间的最大值.