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 允许您异步调用任何方法. 为此,应定义与您要调用的方法具有相同签名的委托:公共语言运行时会自动使用适当的签名为该委托定 ...
随机推荐
- AIX rcp跨主机远程
rcp用途:在本地主机和远程主机之间或者两个远程主机之间传输文件.详细用法可man rcp查看. 现在要把主机10.200.5.200的/tmp/work.sh(属主为root用户)拷贝到远程主机18 ...
- Tarjan模版(链式向前星表示方法)
这道模版用到了链式向前星表示法: struct node { int v,next; }edge[]; void add(int x,int y) { edge[++cnt].next=heads[x ...
- 异步fifo的读写
这里不讨论异步fifo是如何实现的,而是在实现fifo的前提下,对fifo的读写. 现在遇到的问题是:总线的数据不能写入fifo中,但是地址能加一. 代码如下: if( !fifo_tx_full & ...
- Oracle 11G的间隔(INTERVAL)分区
-- Create table create table MS_BIGTABLE_LOG ( record_date DATE, col_1 VARCHAR2(), col_2 VARCHAR2() ...
- 用python40行代码编写的计算器
效果图 代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 ...
- ffmpeg截取一段视频中一段视频
ffmpeg -i ./plutopr.mp4 -vcodec copy -acodec copy -ss 00:00:10 -to 00:00:15 ./cutout1.mp4 -y -ss ti ...
- 从官网下载jdk1.6 1.7
Oracle Java Archive | Oracle Technology Network | Oraclehttp://www.oracle.com/technetwork/java/javas ...
- webmagic使用
webmagic是Java语言用于爬虫的工具.官网地址:http://webmagic.io/,中文文档地址:http://webmagic.io/docs/zh/ 使用webmagic有3种配置需要 ...
- linux lvs 配置
redhatAS4.2 安装集群LVS 环境描述: 本文在配置LVS时使用三台linux,一台做Directorserver (192.168.0.25) ,两台做realserver(192.168 ...
- C++——STL容器
序列式容器:vector,list,deque:stack,queue(容器适配器),heap,priority_queue,slist 关联式容器:(底层都是红黑树)set,map,multiset ...