使用委托实现同步回调与异步回调

使用委托可以执行的一项有用操作是实现回调。回调是传入函数的方法,在函数结束执行时调用该方法。

例如,有一个执行一系列数学操作的函数。在调用该函数时,也向其传递一个回调方法,从而在函数完成其计算工作时,调用回调方法,向用户通知计算结果。

同步回调

   首先声明两个方法:

AddTwoNumbers():接受两个整型实参以及一个类型委托

ResultCallback():接受一个字符串,并显示出来。代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DelegateCallBack
{
    class Program
    {
        delegate void CallbackDelegate(string msg);

        static void Main(string[] args)
        {
            //方式一:
            CallbackDelegate result = ResultCallback;
            AddTwoNumbers(5, 3, result);

            //方式二:
            AddTwoNumbers(5, 3, ResultCallback);

            Console.Read();
        }

       

        static private void AddTwoNumbers(int num1,int num2,CallbackDelegate callback)
        {
            int result = num1 + num2;

            callback(result.ToString());
        }

        static private void ResultCallback(string msg)
        {
            Console.WriteLine(msg);
        }
    }
}

异步回调

回调在异步情况下最有用。前面实例中说明的回调是同步回调,也就是按顺序调用函数。如果AddTwoNumbers方法花费较长时间来执行,则该函数之后的所有的语句将被阻塞。 组织较好的方式是异步调用AddTwoNumbers方法。异步调用函数允许主程序继续执行,而不需要等待该函数返回。 在这种异步模型中,当调用AddTwoNumbers函数时,在其后的语句继续执行。当函数结束时,他调用ResultCallback函数。

下面使用异步回调重写前面的程序:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading.Tasks;

namespace DelegateCallBack
{
    class Program
    {
        delegate int MethodDelegate(int num1, int num2);

        static void Main(string[] args)
        {
           
            MethodDelegate result = AddTwoNumbers;

            //引用异步操作完成时调用的方法
            AsyncCallback callback = new AsyncCallback(ResultCallback);

            Console.WriteLine("开始异步调用");

            IAsyncResult iresult = result.BeginInvoke(5, 3, callback, null);

            Console.WriteLine("主程序继续执行");

   
            Console.Read();
        }

       

        static private int AddTwoNumbers(int num1,int num2)
        {
            int result = num1 + num2;

            System.Threading.Thread.Sleep(5000);

            return result;
        }

        static private void ResultCallback(IAsyncResult ar)
        {
            MethodDelegate dele = (MethodDelegate)((AsyncResult)ar).AsyncDelegate;

            int result = dele.EndInvoke(ar);

            Console.WriteLine("result={0}",result);
        }
    }
}

程序一运行:

五秒后

现在我们分析下程序,首先我们定义一个委托类型,从而可以指向AddTwoNumbers方法。

接下来,定义一个类型为AsyncCallback的委托。AsyncCallback是引用某个方法的委托,当异步操作完成时调用该方法。

使用result 委托的BeginInvoke()方法异步调用AddTwoNumbers(),并且向该方法传递两个整型以及在该方法结束执行时回调的委托。

BeginInvoke()方法异步调用委托,在调用异步委托之后,下一条语句会继续执行。该方法返回类型为IAsyncResult 的变量,该变量表示异步操作的状态。

在ResultCallback方法中,首先使用AsyncDelegate特性获得指向AddTwoNumbers()方法的委托,该特性返回进行异步调用的委托。接下来,使用EndInvoke()方法会的异步调用的结果,向该方法传递IAsycResult变量。

在使用异步回调时,可以通过在不同的线程中执行程序的不同部分来使程序更快速的响应。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏大内老A

ASP.NET MVC三个重要的描述对象:ActionDescriptor

在Model绑定过程中会通过激活的Controller类型创建用于描述它的ControllerDescriptor对象。Controller是一组Action方...

1877
来自专栏技术博客

C#简单的面试题目(三)

31.C#提供一个默认的无参构造函数,当我实现了另外一个有一个参数的构造函数时,还想保留这个无参数的构 造函数。这样我应该写几个构造函数?     两个,一...

2081
来自专栏码洞

见微知著 —— Redis 字符串内部结构源码分析

继上篇讲解了字典的内部结构 之后,本篇我们开始讲字典 key 的内部结构,也就是 sds 字符串。首先它不是普通字符串,而是 sds 字符串,这个 sds 的意...

871
来自专栏一枝花算不算浪漫

[读书笔记]C#学习笔记七: C#4.0中微小改动-可选参数,泛型的可变性

3468
来自专栏NetCore

.NET反射、委托技术与设计模式

1 反射技术与设计模式   反射(Reflection)是。NET中的重要机制,通过放射,可以在运行时获得。NET中每一个类型(包括类、结构、委托、接口和枚举...

2129
来自专栏大内老A

ASP.NET MVC中的ActionFilter是如何执行的?

在ASP.NET MVC中的四大筛选器(Filter),ActionFilter直接应用在某个Action方法上,它在目标Action方法执行前后对调用进行拦截...

2147
来自专栏编程

经常出现却又容易被忽略的Java SE面试题 必看

在面试的过程中往往会遇到javase的题目,这个又是容易被忽略,来看一下是哪些呢? 1)运行时异常,非运行时异常。 运行时异常可进行处理,也可不进行处理。非运行...

2025
来自专栏GreenLeaves

C# foreach循环较for循环的优势与劣势

一、foreach循环的优势 C#支持foreach关键字,foreach在处理集合和数组相对于for存在以下几个优势: 1、foreach语句简洁 2、效率比...

1978
来自专栏大内老A

What is "Type" in managed heap?

我们知道,在程序运行过程中,每个对象(object)都是对应了一块内存,这里的对象不仅仅指的是某个具体类型的实例(instance),也包括类型(type)本身...

1867
来自专栏Java帮帮-微信公众号-技术文章全总结

通过字节码分析JDK8中Lambda表达式编译及执行机制【面试+工作】

在Class文件中,方法调用即是对常量池(ConstantPool)属性表中的一个符号引用,在类加载的解析期或者运行时才能确定直接引用。

1221

扫码关注云+社区