C#回调机制解析

本文通过实例解析了C#中的回调机制,展示了如何利用回调实现异步调用,包括定义委托、异步调用及回调函数的具体应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文转载自http://blog.youkuaiyun.com/liuyimu/article/details/5552349

C#回调机制实例解析

    周四设计模式的课上,老师说到了回调机制的问题。本文实例解析了C#中回调机制的应用方法。

1.什么是回调

软件模块之间总是存在着一定的接口,从调用方式上,可以把他们分为三类:同步调用、回调和异步调用。同步调用是一种阻塞式调用,调用方要等待对方执行完毕才返回。回调是一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口;异步调用是一种类似消息或事件的机制,接口的服务在收到某种讯息或发生某种事件时,会主动通知客户方(即调用客户方的接口)。回调和异步调用的关系非常紧密,通常我们使用回调来实现异步消息的注册,通过异步调用来实现消息的通知,因此可知回调机制是实现异步调用的基础。因此,下面我们着重讨论回调机制在异步调用中的作用【1】。

 下图展示了一次异步调用的结构图:

 

 模块A对模块B进行异步调用,调用立即返回。待模块B中的方法执行完毕之后,通过回调机制(促发模块A中声明的回调函数)通知模块A调用完毕,并可以返回调用的结果。

2.C# Framework下异步调用

        废话不说,先看一个C#中异步调用的实例,此实例来改编至金旭亮老师的《.net 2.0面向对象编程揭秘》一书,代码经过了适当的修改,从而符合图一所示的结构图。

        

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.IO;  
  6.   
  7. namespace CallbackTest  
  8. {  
  9.     class FileSize  // 对应图一中的模块B  
  10.     {  
  11.         //计算指定文件夹的总容量  
  12.         public static long CalculateFolderSize(string FolderName)  
  13.         {  
  14.             if (Directory.Exists(FolderName) == false)  
  15.             {  
  16.                 throw new DirectoryNotFoundException("文件夹不存在");  
  17.             }  
  18.   
  19.             DirectoryInfo RootDir = new DirectoryInfo(FolderName);  
  20.             //获取所有的子文件夹  
  21.             DirectoryInfo[] ChildDirs = RootDir.GetDirectories();  
  22.             //获取当前文件夹中的所有文件  
  23.             FileInfo[] files = RootDir.GetFiles();  
  24.             long totalSize = 0;  
  25.             //累加每个文件的大小  
  26.             foreach (FileInfo file in files)  
  27.             {  
  28.                 totalSize += file.Length;  
  29.             }  
  30.             //对每个文件夹执行同样的计算过程:累加其下每个文件的大小  
  31.             //这是通过递归调用实现的  
  32.             foreach (DirectoryInfo dir in ChildDirs)  
  33.             {  
  34.                 totalSize += CalculateFolderSize(dir.FullName);  
  35.             }  
  36.             //返回文件夹的总容量  
  37.             return totalSize;  
  38.         }  
  39.   
  40.     }  
  41.     class Program  //对应于图一中的模块A  
  42.     {  
  43.         //定义一个委托  
  44.         public delegate long CalculateFolderSizeDelegate(string FolderName);  
  45.   
  46.         // 初始化一个委派实例d,指向FileSize中类的CalculateFolderSize函数  
  47.         private static CalculateFolderSizeDelegate d = new CalculateFolderSizeDelegate(FileSize.CalculateFolderSize);  
  48.   
  49.   
  50.         //用于实现回调机制的回调函数,注意到该函数在模块一  
  51.         public static void ShowFolderSize(IAsyncResult result)  
  52.         {  
  53.             try  
  54.             {  
  55.                 long size = d.EndInvoke(result);  
  56.   
  57.                 Console.WriteLine("/n文件夹{0}的容量为:{1}字节/n", (String)result.AsyncState, size);  
  58.   
  59.             }  
  60.             catch (DirectoryNotFoundException e)  
  61.             {  
  62.                 Console.WriteLine("您输入的文件夹不存在");  
  63.             }  
  64.   
  65.         }  
  66.         static void Main(string[] args)  
  67.         {  
  68.             string InputFolderName;  
  69.        
  70.             Console.WriteLine("请输入文件夹名称(例如:C://Windows),输入quit结束程序");  
  71.   
  72.             InputFolderName = Console.ReadLine();  
  73.   
  74.             d.BeginInvoke(InputFolderName, ShowFolderSize, InputFolderName);  
  75.             Console.WriteLine("Now calculating,Please waiting......"); //注意这一行代码  
  76.             Console.ReadLine();  
  77.         }  
  78.     }  
  79. }  

        运行结果如下图所示:

        

          请注意,在计算出文件夹的大小之前,也就是在CalculateFolderSize返回之前,Console.WriteLine("Now calculating,Please waiting......")这行代码已经被执行了,这就是异步调用的作用!

下面我们逐行解析这里面的代码。

    首先看 public static void ShowFolderSize(IAsyncResult result)这个回调函数,注意到这是一个静态函数,返回值为void,参数类型为IAsyncResult(实际上是一个接口,详见MSDN),此参数包含外界传入的信息。

再看d.BeginInvoke(InputFolderName, ShowFolderSize, InputFolderName)这行代码,函数BeginInvoke的函数原型如下:

Public IAsyncResult BeginInove

{

<委托确定的方法签名中的参数列表,可能不止一个>,

AsyncCallback callback, object asyncState

}

其中第二个参数callback是异步调用结束时自动回调的函数,第三个参数asyncState用于向callback这个回调函数传递参数。

好了,现在整个程序的逻辑就很清楚了,在模块A中异步调用模块B中的CalculateFolderSize方法计算给定的文件夹的大小,并且指定模块A中的方法ShowFolderSize作为回调函数。

全文完

 

参考文献:【1】  陈家朋  异步消息传递——回调机制 IBM开发者网络 http://www.ibm.com/developerworks/cn/linux/l-callback/

                 【2】 金旭亮 《.NET 2.0 面向对象编程揭秘》 第13章 P454~P462


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值