• Control.BeginInvoke()和delegate的BeginInvoke()的区别


    最近在一个demo中了解到可以用BeginInvoke来处理异步,于是我也自己做了一个winform来学习BeginInvoke。

    在窗体上放置了一个按钮和一个label,点击按钮3秒后再label上显示“Hello World”。先是有了如下代码:

    复制代码
     1         private void btnStart_Click(object sender, EventArgs e)
     2         {
     3             BeginInvoke(new xDel(k =>
     4             {
     5                 Thread.Sleep(k);
     6                 txtMain.Text = "Hello World";
     7             }), 3000);
     8         }
     9 
    10         delegate void xDel(int i);
    复制代码

    点击按钮后调用BeginInvoke执行异步,传递一个委托。按照我的设想,应该BeginInvoke应该是创建一个新线程执行委托,所以不会造成UI假死。

    但是结果是运行后UI还是假死了。

    后来上网查找了一些资料才发现,原先看的demo里使用的委托的BeginInvoke方法,而我写的BeginInvoke是属于Control类的。正确的写法应该是:

    复制代码
     1  private void btnStart_Click(object sender, EventArgs e)
     2         {
     3             xDel xd = new xDel(t =>
     4             {
     5                 Thread.Sleep(t);
     6                 BeginInvoke(new Action(() =>
     7                 {
     8                     txtMain.Text = "Hello World";
     9                 }));
    10             });
    11             xd.BeginInvoke(3000, null, null);
    12         }
    13 
    14         delegate void xDel(int i);
    复制代码

    这两者的区别在于委托的BeginInvoke方法是新起一个线程来执行委托,而原线程继续往下执行;Control.BeginInvoke则是将委托强制传递至UI线程执行,所以可能会造成UI线程假死。

    所以想要执行异步,应该用delegate的BeginInvoke方法;而Control.BeginInvoke方法主要用途是让子线程可以跨线程操作UI线程的控件,正如代码2的第六行一样。

  • 相关阅读:
    Linux下DNS服务器搭建详解
    Oracle 数据泵使用详解--精华版
    Oracle 数据泵详解
    数据泵
    Oracle11g数据库导入Oracle10g数据库操作笔记
    DNS服务器
    spring mvc发送请求404,不能进入处理方法,也不报错
    CentOS设置默认启动命令行(不启动图形界面)
    SQL Server 排序的时候使 null 值排在最后
    Git教程
  • 原文地址:https://www.cnblogs.com/wwwbdabc/p/11653060.html
Copyright © 2020-2023  润新知