发文章
发文工具
撰写
网文摘手
文档
视频
思维导图
随笔
相册
原创同步助手
其他工具
图片转文字
文件清理
AI助手
留言交流
历史上,Windows API经常使用C语言风格的函数指针来创建称为回调函数或简称为回调的实体。使用回调,码农可以使一个函数返回报告给(即回调)程序中的另一个函数。
在.NET Framework里,回调仍是可能的,它们的功能是由使用更为安全和面向对象的委托(delegate)来完成的。本质上来讲,委托是一个类型安全的对象,它指向程序中另一个以后会被调用的方法(或多个方法)。委托类型包含3个得要的信息:
当一个委托被创建并提供了上述信息后,它可以在运行时动态调用其指向的方法。可以看到,.NET Framwwork中每个委托(包括自定义委托)都被自动赋予同步或异步访问方法的能力,可以不用手工创建与管理一个Thread对象而直接调用另一个辅助执行线程上的方法,这大大简化了编程工作。
使用C#定义委托:假定我们要创建一个名为BinaryOp的委托,它可以指向任何输入两个整数返回一个整数的方法:
public delegate int BinaryOp(int x,int y);
当C#编译器处理委托类型时,它先自动产生一个派生自System.MulticastDelegaet的密封类。这个类与它的基类System.Degelate 一起为委托提供必要的基础设施,以维护以后将要调用方法的列表。
写着写着突然没电,没保存,比改需求还痛苦,没办法,只能重来。
如果我们通过ildasm.exe来查看BinaryOp委托可以看到,生成的BinaryOp类定义了三个公共方法。Invoke()可能是核心方法,因为它被用来以同步方式调用委托类型维护的每个方法。BeginInvoke()和EndInvoke()方法能在第二个执行线程上异步调用当前方法。
编译器是如何确切知道怎样定义Invoke()、BeginInvoke()和EndInvoke()方法的呢?欲知后事如何,请看下面代码:
sealed class BinaryOp:System.MulticastDelegate { public BinaryOp(object target,uint functionAddress); public int Invoke(int x,int y); public IAsyncResult BeginInvoke(int x,int y,AsyncCallback cb,object state); public int EndInvoke(IAsyncResult result); }
初次接触委托可能会感觉很难。不要紧,接下来,让我们看一个非常简单的使用BinaryOp委托的示例,我们以前见过,这是一个名为Simple Delegate的控制台应用程序项目。
namespace SimpleDelegate { // 委托其实就相当于一个类型。这里,类型的名字叫BinaryOp public delegate int BinaryOp(int x,int y); class SimpleMath { public static int Add(int x, int y) { return x + y; } public static int Substract(int x, int y) { return x - y; } } class Program { static void Main(string[] args) { // 创建一个BinaryOp类型的实例,用静态Add方法初始化 BinaryOp d = new BinaryOp(Add); Console.WriteLine(d(10, 10)); Console.ReadLine(); } } }
.net委托是类型安全的。所以如果读者试图将一个不匹配模式的方法传入委托,将会收到编译期错误。例如,假定SimpleMath类定义了一个名为SquareNumber()的方法:
public class SimpleMath{ ... public static int SquareNumber(int a) { return a*a; } }
由于BinaryOp委托公可指向带有两个整数参数并返回一个整数的方法下面这段代码是非法的,将无法编译:
//错误!方法不匹配委托的模式 BinaryOp b2=new BinaryOp(SimpleMath.SquareNumber);
委托对象
我们在program类型中创建一个名为DisplayDegelateInfo()的静态方法丰富当前的示例。这个方法将输出传入的委托类型所维护的方法的名称和定义该方法的类的名称。通过迭代由GetInvocationList()返回的System.Delegate数组,调用每个对象的Target和method属性:
static void DisplayDelegateInfo(Delegate delObj) { foreach(Delegate d in delObj.GetInvocationList()) { Console.WriteLine("Method Name:{0}",d.Method); Console.WriteLine("Type Name:{0}",d.Target); } }
来自: 昵称10504424 > 《工作》
0条评论
发表
请遵守用户 评论公约
多线程(一):异步委托
-->//在次线程中调用Add()IAsyncResult iftAr = b.BeginInvoke(10, 10, null, null);Code-->static void AddComplete(IAsyncResult itfAR){WriteLine("AddComplete() 执行在线程on thread {...
关于委托和事件的使用
/** 题外话,上图提到的Balsamiq Mockups是一个很棒的软件, 可以用来画UI效果图, 我喜欢用来画流程图(稍显不如visio方便, 但是阅读...
C#线程中安全访问控件(重用委托,避免繁复的delegate,Invoke)总结
C#线程中安全访问控件(重用委托,避免繁复的delegate,Invoke)总结。
C#异步调用四大方法详解
namespace ConsoleAppAsync { // The delegate must have the same signature as the method // you want to call asynchronously. public delegate string AsyncDelega...
C#委托的异步调用
public class 异步调用{ static void Main() { Console.WriteLine("===== 异步调用 AsyncInvokeTest ====="); AddHandler handler = new AddHandler(加...
C#异步调用的好处和方法
下面你可以很容易想到,回收分为2种情况:主动回收和被动回收(当然,这是我自己的理解,微软可不是这么说的),主动回收就是,你去监视那个线程,并且等待,当异步方法完成了,就把异步线程回收,焦点...
C#异步调用的应用浅析
//参数dn相当于该线程的ID,如果有多个C#异步调用线程, //可以都是null,但是绝对不能一样,不能是同一个object,否则异常 IAsyncResult iar = dn.BeginInvoke(1, out i, acb, dn); //去做别的事...
.NET异步编程总结
WriteLine("主线程"); IAsyncResult result = printDelegate.BeginInvoke("Hello World.", null, null); Console.W...
MSDN
这称为BeginInvoke,它与异步委托调用很相似,与委托的明显区别在于,该调用以异步方式在线程池的某个线程上运行,然而在此处,它以异步方式在 UI线程上运行。它可从任何线程读取,如果调用线程是 UI线...
微信扫码,在手机上查看选中内容