关于C#委托三种调用的分享
一、同步调用
1、同步调用会按照代码顺序来执行
2、同步调用会阻塞线程,如果是要调用一项繁重的工作(如大量IO操作),可能会让程序停顿很长时间,造成糟糕的用户体验,这时候异步调用就很有必要了。
举个栗子:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading; namespace Test
{
public delegate int AddHandler(int a, int b);
public class Calc
{
public static int Add(int a, int b)
{
Console.WriteLine("开始计算:" + a + "+" + b);
Thread.Sleep(); //模拟该方法运行三秒
Console.WriteLine("计算完成!");
return a + b;
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("===== 同步调用 SyncInvokeTest =====");
AddHandler handler = new AddHandler(Calc.Add);
int result = handler.Invoke(, );
Console.WriteLine("继续做别的事情。。。");
Console.WriteLine(result);
Console.ReadKey();
}
}
}
* 问:为什么Invoke的参数和返回值和AddHandler委托是一样的呢?
* 答:Invoke方法的参数很简单,一个委托,一个参数表(可选),
而Invoke方法的主要功能就是帮助你在UI线程上调用委托所指定的方法。
Invoke方法首先检查发出调用的线程(即当前线程)是不是UI线程,
如果是,直接执行委托指向的方法,如果不是,它将切换到UI线程,
然后执行委托指向的方法。不管当前线程是不是UI线程,
Invoke都阻塞直到委托指向的方法执行完毕,然后切换回发出调用的
线程(如果需要的话),返回。
所以Invoke方法的参数和返回值和调用他的委托应该是一致的。

二、异步调用
1、异步调用不阻塞线程,而是把调用塞到线程池中,
2、程序主线程或UI线程可以继续执行。
3、委托的异步调用通过BeginInvoke和EndInvoke来实现。
举个栗子:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading; namespace Test
{
public delegate int AddHandler(int a, int b);
public class Calc
{
public static int Add(int a, int b)
{
Console.WriteLine("开始计算:" + a + "+" + b);
Thread.Sleep(); //模拟该方法运行三秒
Console.WriteLine("计算完成!");
return a + b;
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("===== 异步调用 AsyncInvokeTest =====");
AddHandler handler1 = new AddHandler(Calc.Add);
//IAsyncResult: 异步操作接口(interface)
//BeginInvoke: 委托(delegate)的一个异步方法的开始
IAsyncResult result1 = handler1.BeginInvoke(, , null, null); Console.WriteLine("继续做别的事情1。。。");
//异步操作返回
Console.WriteLine(handler1.EndInvoke(result1));//会等待加法类计算,如果没计算好就堵塞线程
Console.WriteLine("继续做别的事情2。。。");
Console.ReadKey();
}
}
}
注意:
* BeginInvoke : 开始一个异步的请求,调用线程池中一个线程来执行,
* 返回IAsyncResult 对象(异步的核心). IAsyncResult 简单的说,
* 它存储异步操作的状态信息的一个接口,也可以用他来结束当前异步。
* 注意: BeginInvoke和EndInvoke必须成对调用.即使不需要返回值,
* 但EndInvoke还是必须调用,否则可能会造成内存泄漏。

结果:
可以看到,主线程并没有等待,而是直接向下运行了。
但是问题依然存在,当主线程运行到EndInvoke时,如果这时调用没有结束(这种情况很可能出现),这时为了等待调用结果,线程依旧会被阻塞。
三、异步回调
用回调函数,当调用结束时会自动调用回调函数,解决了为等待调用结果,而让线程依旧被阻塞的局面。
举个栗子:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading; namespace Test
{
public delegate int AddHandler(int a, int b);
public class Calc
{
public static int Add(int a, int b)
{
Console.WriteLine("开始计算:" + a + "+" + b);
Thread.Sleep(); //模拟该方法运行三秒
Console.WriteLine("计算完成!");
return a + b;
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("===== 异步回调 AsyncInvokeTest =====");
AddHandler handler2 = new AddHandler(Calc.Add);
//异步操作接口(注意BeginInvoke方法的不同!)
IAsyncResult result2 = handler2.BeginInvoke(, , new AsyncCallback(MyCallBack),
"AsycState:OK");
Console.WriteLine("继续做别的事情。。。");
Console.ReadKey();
}
static void MyCallBack(IAsyncResult result)
{
//result 是“加法类.Add()方法”的返回值
//AsyncResult 是IAsyncResult接口的一个实现类,空间:System.Runtime.Remoting.Messaging
//AsyncDelegate 属性可以强制转换为用户定义的委托的实际类。
AddHandler handler = (AddHandler)((AsyncResult)result).AsyncDelegate;
Console.WriteLine(handler.EndInvoke(result));
Console.WriteLine(result.AsyncState);
}
}
}
委托的类型为AddHandler,则为了访问 AddHandler.EndInvoke,
result 是“加法calc.Add()方法”的返回值
AsyncResult 是IAsyncResult接口的一个实现类,空间:System.Runtime.Remoting.Messaging
必须将异步委托强制转换为 AddHandler。可以在异步回调函数(类型为 AsyncCallback)中调用 AddHandler.EndInvoke,以获取最初提交的 AddHandler.BeginInvoke 的结果。

ok,三种委托调用的分享就到这里了,有疑问的欢迎指正!
关于C#委托三种调用的分享的更多相关文章
- 【转】SVG与HTML、JavaScript的三种调用方式
原文:https://www.cnblogs.com/guohu/p/5085045.html SVG与HTML.JavaScript的三种调用方式 一.在HTMl中访问SVG的DOM 1 2 3 4 ...
- Vue组件的三种调用方式
最近在写fj-service-system的时候,遇到了一些问题.那就是我有些组件,比如Dialog.Message这样的组件,是引入三方组件库,比如element-ui这样的,还是自己实现一个?虽然 ...
- C# 委托的三种调用示例(同步调用 异步调用 异步回调)
首先,通过代码定义一个委托和下面三个示例将要调用的方法: 复制代码 代码如下: public delegate int AddHandler(int a,int b); public class ...
- C# 委托的三种调用示例(同步调用、异步调用、异步回调)
首先,通过代码定义一个委托和下面三个示例将要调用的方法: 代码如下: public delegate int AddHandler(int a,int b); public class 加法类 { p ...
- 20160711--C# 委托的三种调用示例(同步调用 异步调用 异步回调)【转载】
首先,通过代码定义一个委托和下面三个示例将要调用的方法: 代码如下: public delegate int AddHandler(int a,int b); public class 加法类 { p ...
- unity中三种调用其他脚本函数的方法
第一种,被调用脚本函数为static类型,调用时直接用 脚本名.函数名()第二种,GameObject.Find("脚本所在的物体的名字").SendMessage(" ...
- vue-methods三种调用的形势
var btn = { template:`<button>组件add</button>` } var any = new Vue({ el: '#app', data:{ a ...
- 委托(delegate)的三种调用方式:同步调用,异步调用,异步回调(转载)
下面为即将被调用的方法: public delegate int AddHandler(int a,int b); public class 加法类 { public static int Add(i ...
- java三种调用方式(同步调用/回调/异步调用)
1:同步调用:一种阻塞式调用,调用方要等待对方执行完毕才返回,它是一种单向调用 2:回调:一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口: 3:异步调用:一种类似消息或事件的机制 ...
随机推荐
- 记录下做攻防世界的misc题
0x00 记录一下,代表自己做过 0x01 flag_universe 看简介是来自2018年的百越杯. 将文件下载下来后,就一个flag_universe.pcapng文件,wireshark打开. ...
- delete old data in elasticsearch
delete old data in elasticsearch 0.正文. 其实很简单,就是用他的rest api 发一个delete 请求到 localhost:9200/[indices] [i ...
- Node.js服务器创建和使用
1.使用zlib模块对服务器端响应压缩 //1.1引入zlib模块 const zlib=require('zlib'); //1.2 设置内容的压缩形式 'Content-Encoding': 'g ...
- linux ,mac连接, git pull error, chmod修改文件的权限/chown修改文件和目录的所有者
去项目目录下 启动服务 setsid npm start & Mac下如何用SSH连接远程Linux服务器 https://www.cnblogs.com/littleBit/p/536280 ...
- 安装的SQL Server2008 R2版的连接不到本地数据,提示未找到或无法访问服务器。----复制自百度知道
安装的SQL Server2008 R2版的连接不到本地数据,提示未找到或无法访问服务器.使用Windows身份验证 2012-09-17 00:23hj168926 | 分类:数据库DB | 浏览3 ...
- 日志文件的配置----【logback-spring.xml】
一.引入相关包 <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-c ...
- hdu5984概率数学
转载 https://www.oyohyee.com/post/HDU/5984.html
- DQN(Deep Q-learning)入门教程(一)之强化学习介绍
什么是强化学习? 强化学习(Reinforcement learning,简称RL)是和监督学习,非监督学习并列的第三种机器学习方法,如下图示: 首先让我们举一个小时候的例子: 你现在在家,有两个动作 ...
- Android数据传递
直接用一个例子说明,简单粗暴: 数据传递会用到此界面标注id值的三个控件 Activity_zc.xm l 当点击“注册”按钮,会显示注册信息 Activity._show.xml 下面展示zcAct ...
- Mybatis配置-简单的使用
导包 基本配置 配置mybatis.config.xml文档 <?xml version="1.0" encoding="UTF-8" ?> < ...