C#委托同步异步说明,并比较control调用Invoke和BeginInvoke的异同
一.委托的同步和异步:
1.同步
使用Invoke调用同步,或直接写fun1("func"),在fun1.Invoke这一步会明显的阻塞线程
使用:
static void Main(string[] args)
{
Thread.CurrentThread.Name = "Main"; //定义一个带返回值的委托
var fun1 = new Func<string, int>(x =>
{
Thread.Sleep(1000);
Console.WriteLine(x);
Console.WriteLine($"ThreadId:{Thread.CurrentThread.ManagedThreadId} ThreadName:{Thread.CurrentThread.Name}");
return 1;
}); fun1.Invoke("fun1"); Console.WriteLine("Main");
Console.WriteLine($"ThreadId:{Thread.CurrentThread.ManagedThreadId} ThreadName:{Thread.CurrentThread.Name}");
Console.ReadKey();
}
运行结果:

结果说明:
同步委托运行在主线程上
2.异步
使用BeginInvoke来调用异步,EndInvoke来获取返回值,AsyncCallback定义异步完成回调函数
使用:
static void Main(string[] args)
{
Thread.CurrentThread.Name = "Main"; //定义一个带返回值的委托
var fun1 = new Func<string, int>(x =>
{
Thread.CurrentThread.Name = "fun1";
Console.WriteLine(x);
Console.WriteLine($"ThreadId:{Thread.CurrentThread.ManagedThreadId} ThreadName:{Thread.CurrentThread.Name}");
return 1;
}); fun1.BeginInvoke("fun1", t =>
{
//var fun2 = t.AsyncState as Func<string, int>;//如果不是lambda表达式需要用该方式获得委托
//获取返回值
int ret = fun1.EndInvoke(t);
Console.WriteLine($"callback return:{ret}");
Console.WriteLine($"ThreadId:{Thread.CurrentThread.ManagedThreadId} ThreadName:{Thread.CurrentThread.Name}"); }, null); Thread.Sleep(1000);
Console.WriteLine("Main");
Console.WriteLine($"ThreadId:{Thread.CurrentThread.ManagedThreadId} ThreadName:{Thread.CurrentThread.Name}");
Console.ReadKey();
}
运行结果:

结果说明:
异步委托并不是运行在主线程上,而是运行在独立的线程上,是异步执行的
二.control的Invoke和BeginInvoke
1.Invoke
使用:
private void button1_Click(object sender, EventArgs e)
{
Thread.CurrentThread.Name = "UIThread";
this.Invoke(new Action(() =>
{
Thread.Sleep(5000);
Debug.WriteLine($"Invoke ThreadId:{Thread.CurrentThread.ManagedThreadId} ThreadName:{Thread.CurrentThread.Name}");
})); Debug.WriteLine($"Main ThreadId:{Thread.CurrentThread.ManagedThreadId} ThreadName:{Thread.CurrentThread.Name}");
}
运行结果:

结果说明:
可以明显的感到Invoke阻塞了界面5s后,才执行后面的代码
Invoke内的委托在UI线程上执行,是同步的
2.BeginInvoke
使用:
private void button1_Click(object sender, EventArgs e)
{
Thread.CurrentThread.Name = "UIThread"; this.BeginInvoke(new Action(() =>
{
Debug.WriteLine($"BeginInvoke ThreadId:{Thread.CurrentThread.ManagedThreadId} ThreadName:{Thread.CurrentThread.Name}");
})); Debug.WriteLine($"Main ThreadId:{Thread.CurrentThread.ManagedThreadId} ThreadName:{Thread.CurrentThread.Name}");
Thread.Sleep(5000);
}
运行结果:

结果说明:
可以明显看到界面卡了5s后,才先执行的BeginInvoke内的委托
结论:BeginInvoke内的委托在UI线程上执行,并不是异步,只是放在UI线程中最后执行。
三.结论
| delegate.Invoke | 运行在主线程上,同步执行,并立即执行,会阻塞主线程 |
| delegate.BeginInvoke | 运行在独立线程上,异步执行, 并立即执行,不会阻塞主线程 |
| Control.Invoke | 运行在UI线程上,同步执行,并立即执行,会阻塞UI线程 |
| Control.BeginInvoke | 运行在UI线程上,不是异步执行,等UI线程其他操作完成才执行,会阻塞UI线程 |
C#委托同步异步说明,并比较control调用Invoke和BeginInvoke的异同的更多相关文章
- Control的Invoke和BeginInvoke详解
(一)Control的Invoke和BeginInvoke 我们要基于以下认识: (1)Control的Invoke和BeginInvoke与Delegate的Invoke和BeginInvoke是不 ...
- [转]Control的Invoke和BeginInvoke
转自:Control的Invoke和BeginInvoke 作者:Kuffy Wang 近日,被Control的Invoke和BeginInvoke搞的头大,就查了些相关的资料,整理如下.感谢这篇文 ...
- C#中Control的Invoke和BeginInvoke是相对于支线线程
近日,被Control的Invoke和BeginInvoke搞的头大,就查了些相关的资料,整理如下. Control的Invoke和BeginInvoke 是相对于支线线程(因为一般在支线线程中调用, ...
- Control的Invoke和BeginInvoke
转载:https://www.cnblogs.com/c2303191/articles/826571.html 近日,被Control的Invoke和BeginInvoke搞的头大,就查了些相关的资 ...
- 【分析】浅谈C#中Control的Invoke与BeginInvoke在主副线程中的执行顺序和区别(SamWang)
[分析]浅谈C#中Control的Invoke与BeginInvoke在主副线程中的执行顺序和区别(SamWang) 今天无意中看到有关Invoke和BeginInvoke的一些资料,不太清楚它们之间 ...
- [转载]Winform中Control的Invoke与BeginInvoke方法
转自http://www.cppblog.com/baby-fly/archive/2010/04/01/111245.html 一.为什么 Control类提供了 Invoke和 BeginInvo ...
- 委托(delegate)的三种调用方式:同步调用,异步调用,异步回调(转载)
下面为即将被调用的方法: public delegate int AddHandler(int a,int b); public class 加法类 { public static int Add(i ...
- C#--委托的同步,异步,回调函数
原文地址 同步调用 委托的Invoke方法用来进行同步调用.同步调用也可以叫阻塞调用,它将阻塞当前线程,然后执行调用,调用完毕后再继续向下进行. using System; using System. ...
- C#使用委托进行异步编程。
首先引用MSDN中的一段话来描述一下如何使用异步方式.NET Framework 允许您异步调用任何方法. 为此,应定义与您要调用的方法具有相同签名的委托:公共语言运行时会自动使用适当的签名为该委托定 ...
随机推荐
- MyBatis collection的两种形式——MyBatis学习笔记之九
与association一样,collection元素也有两种形式,现介绍如下: 一.嵌套的resultMap 实际上以前的示例使用的就是这种方法,今天介绍它的另一种写法.还是以教师映射为例,修改映射 ...
- 第三方引擎应用场景分析--Tokudb,infobright
TokuDBTokuDB的特色:• Fractal Tree而不是B-Tree• 内部结点不仅有指向父子的指针还有Buffer区,数据写入先写buffer区,FIFO结构,写入只需要顺序添加到Buff ...
- ARM-Linux移植之(三)——init进程启动流程分析
我们通常使用Busybox来构建根文件系统的必要的应用程序.Busybox通过传入的参数来决定执行何种操作.当init进程启动时,实际上调用的是Busybox的init_main()函数,下面我们来分 ...
- PHP 取网页变量
$_POST["test"]; $_GET["test"];isset(); if(isset($_GET["yyuid"]))
- python之operator模块
python3中已经没有cmp函数,被operator模块代替,在交互模式下使用时,需要导入模块. 在没有导入模块情况下,会出现 提示找不到cmp函数了,那么在python3中该如何使用这个函数呢? ...
- oracle查询列合并为行(listagg简单用法)
今天工作时遇见一个数据查询分组问题,就是将分组后同一组数据某一列合并为一行,因为之前很少用到,这次工作中刚好有用到,所以手痒难耐,将它记录下来. 查询sql如下: select t.province_ ...
- In function 'int av_clipl_int32_c(int64_t)': error: 'UINT64_C' was not declared in this scope
cygwin下使用ndk编译jni时遇到的错误: /ffmpeg/include/libavutil/common.h: In function 'int av_clipl_int32_c(int64 ...
- LCS(详解)
一,问题描述 给定两个字符串,求解这两个字符串的最长公共子序列(Longest Common Sequence).比如字符串1:BDCABA:字符串2:ABCBDAB 则这两个字符串的最长公共子序列长 ...
- 【HDU6026】Deleting Edges
题意 有一个n个节点的无向图,结点编号从0-n-1,每条边的长度时1to9的一个正整数.现在要删除一些边(或者不删),使得到的新图满足下面两个要求. 1.新图是一颗树有n-1条边2.对于每个结点v(0 ...
- vim 的小幅移动
1.操作符命令和位移 x --->删除一个字符,4x ---->删除4个字符. dw --->可以删除一个单词,d4w ---->删除4个单词. d$ ----> 删除 ...