转自:http://blog.csdn.net/sizheng0320/article/details/1615777

ms-help://MS.MSDNQTR.2003FEB.2052/cpguide/html/cpconusingcallbackfunctions.htm

回调函数是托管应用程序中可帮助非托管 DLL 函数完成任务的代码。对回调函数的调用将从托管应用程序中,通过一个 DLL 函数,间接地传递给托管实现。在用平台调用调用的多种 DLL 函数中,有些函数要求正确地运行托管代码中的回调函数。本主题将介绍托管函数的元素,并说明如何实现回调函数和从托管代码中调用回调函数。

回调函数基础

要从托管代码中调用大多数 DLL 函数,可创建该函数的托管定义,然后调用该函数。此过程比较直接。

要使用需要回调函数的 DLL 函数,则会有一些附加的步骤。首先,必须在文档中查阅该函数,确定该函数是否需要回调。接着,必须在托管应用程序中创建回调函数。最后,调用该 DLL 函数,并将指向回调函数的指针当作参数进行传递。下图总结了这些步骤。

回调函数和实现

回调函数非常适合在重复执行任务的情况下使用。另一个常见用途是与枚举函数(如 Win32 API 中的EnumFontFamiliesEnumPrinters 和 EnumWindows)一起使用。如下一节中的示例所示,EnumWindows 函数将枚举计算机上的所有现有窗口,并调用回调函数来对每个窗口执行一项任务。

实现回调函数

以下过程将说明托管应用程序如何使用平台调用来输出本地计算机上每个窗口的句柄值。尤其是,示例将使用EnumWindows 函数来逐步浏览窗口列表,并使用一个托管回调函数(名为 CallBack)来输出窗口句柄的值。

实现回调函数

  1. 开始实现之前,先查看 EnumWindows 函数的签名。EnumWindows 具有以下签名:

    BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam)

    表示此函数需要回调的线索之一是存在 lpEnumFunc 参数。如果参数采用指向回调函数的指针,其名称中通常会有 lp(长指针)前缀与 Func 后缀的组合。有关 Win32 函数的文档,请参见 Microsoft Platform SDK。

  2. 创建托管回调函数。该示例声明一个名为 CallBack 的委托类型,此委托类型采用两个参数:hwnd 和lparam。第一个参数是窗口的句柄;第二个参数由应用程序定义。在此版本中,这两个参数都必须是整数。

    回调函数通常会返回非零值来表示成功,返回零来表示失败。本示例将返回值显式设置为 true,以继续进行枚举。

  3. 创建一个委托,并将其作为参数传递给 EnumWindows 函数。平台调用会自动将委托转换为常见的回调格式。
  4. 确保在回调函数完成其工作之前,垃圾回收器不会回收委托。如果委托作为参数进行传递,或者所包含的委托作为结构中的字段进行传递,则该委托在调用期间不会被回收。因此,正如下面的枚举示例所示,回调函数会在调用返回前完成其工作,而无需托管调用方执行额外的操作。

    然而,如果可以在调用返回后调用回调函数,则托管调用方必须采取相应的措施来确保委托在回调函数完成其工作之前不会被回收。有关防止垃圾回收的详细信息,请参见用平台调用进行 Interop 封送处理

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace MyDelegate
{
    #region 委托实现回调函数

public delegate bool CallBack(int hwnd, int lParam);

public class EnumReportApp
    {
        [DllImport("user32")]
        //user32.dll中的Win32函数原型为:
        //BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam)
        //表示此函数需要回调的线索之一是存在 lpEnumFunc 参数。如果参数采用指向回调函数的指针,其名称中通常会有 lp(长指针)前缀与 Func 后缀的组合。
        //这里在导入user32.dll后,引入该函数,但是已经将其第一个参数传入了这里定义的委托函数CallBack
        public static extern int EnumWindows(CallBack x, int y);

public static bool Report(int hwnd, int lParam)
        {
            Console.Write("Window handle is ");
            Console.WriteLine(hwnd);
            return true;
        }

public static void Main()
        {
            //实例化一个委托,其实现为上面定义的Report,即调用myCallBack时就是调用了Report
            CallBack myCallBack = new CallBack(EnumReportApp.Report);
            //从这个.NET程序中调用外面user32.dll中的Win32的函数,但是该函数“向回调用(回调)”刚刚定义的.NET程序中的函数myCallBack
            EnumWindows(myCallBack, 0);
            Console.ReadLine();
        }
    }

#endregion
}

MSDN中回调函数的讲解及其C#例子:用委托实现回调函数的更多相关文章

  1. Block、委托、回调函数原理剖析(在Object C语境)——这样讲还不懂,根本不可能!

    开篇:要想理解Block和委托,最快的方法是搞明白“回调函数”这个概念. 做为初级选手,我们把Block.委托.回调函数,视为同一原理的三种不同名称.也就是说,现在,我们把这三个名词当成一回事.在这篇 ...

  2. 在 ASP.NET 网页中不经过回发而以编程方式实现客户端回调

    在 ASP.NET 网页的默认模型中,用户会与页交互,单击按钮或执行导致回发的一些其他操作.此时将重新创建页及其控件,并在服务器上运行页代码,且新版本的页被呈现到浏览器.但是,在有些情况下,需要从客户 ...

  3. 选择列表中的列……无效,因为该列没有包含在聚合函数或 GROUP BY 子句中

    今天用SQL Server尝试实现一个SQL语句的时候,报了如标题所示的错误,通过在百度里面搜索,并亲自动手实现,终于发现问题所在,现在把它记录下来. 语句如下: select [OrderID],[ ...

  4. Mysql学习总结(5)——MySql常用函数大全讲解

    MySQL数据库中提供了很丰富的函数.MySQL函数包括数学函数.字符串函数.日期和时间函数.条件判断函数.系统信息函数.加密函数.格式化函数等.通过这些函数,可以简化用户的操作.例如,字符串连接函数 ...

  5. python format函数/print 函数详细讲解(4)

    在python开发过程中,print函数和format函数使用场景特别多,下面分别详细讲解两个函数的用法. 一.print函数 print翻译为中文指打印,在python中能直接输出到控制台,我们可以 ...

  6. MySQL常用函数大全讲解

    MySQL数据库中提供了很丰富的函数.MySQL函数包括数学函数.字符串函数.日期和时间函数.条件判断函数.系统信息函数.加密函数.格式化函数等.通过这些函数,可以简化用户的操作.例如,字符串连接函数 ...

  7. (转)浅析epoll – epoll函数深入讲解

    原文地址:http://www.cppfans.org/1418.html 浅析epoll – epoll函数深入讲解 前一篇大致讲了一下epoll是个什么东西,优点等内容,这篇延续上一篇的内容,主要 ...

  8. webdriver中的等待——主要讲解WebDriverWait()

    webdriver中的等待--主要讲解WebDriverWait() 强制等待:sleep() 隐式等待:implicitly_wait() 显示等待:WebDriverWait() 与until() ...

  9. 嵌入式&iOS:回调函数(C)与block(OC)回调对比

    学了OC的block,再写C的回调函数有点别扭,对比下区别,回忆记录下. C的回调函数: callBack.h 1).定义一个回调函数的参数数量.类型. typedef void (*CallBack ...

随机推荐

  1. 分布式缓存集群方案特性使用场景(Memcache/Redis(Twemproxy/Codis/Redis-cluster))优缺点对比及选型

    分布式缓存集群方案特性使用场景(Memcache/Redis(Twemproxy/Codis/Redis-cluster))优缺点对比及选型   分布式缓存特性: 1) 高性能:当传统数据库面临大规模 ...

  2. jshint options

    jshint -W032 忽略if代码块后有多余的分号的提示 地址:jslinterrors.com/unnecessary-semicolon asi       忽略函数定义后必须加分号的提示 c ...

  3. uva10002凸包重心

    把每个三角形看成一个质点,坐标就是各自的重心, #include<map> #include<set> #include<cmath> #include<qu ...

  4. Java多态性的理解2

    多态的基础理解请参考:http://www.cnblogs.com/liujinhong/p/6003144.html Java的多态一直是我们理解的一个难点.在读过<深入理解Java虚拟机&g ...

  5. 解决无法启动mysql服务错误1069

    之前在服务器上修改了my.ini文件 mysql就一直无法启动 后来把my.ini改回原来的,还是无法启动并报1069错误 在网上查了一下,基本上都是说修改mysql密码,再重新启动,试了一下没作用, ...

  6. UVA-10972 RevolC FaeLoN (边双连通+缩点)

    题目大意:将n个点,m条边的无向图变成强连通图,最少需要加几条有向边. 题目分析:所谓强连通,就是无向图中任意两点可互达.找出所有的边连通分量,每一个边连通分量都是强连通的,那么缩点得到bcc图,只需 ...

  7. el-table实现表格的编辑、删除、以及新增行的方法

    直接上代码: html部分: <el-form :model="inServForm" ref="inServForm" label-width=&quo ...

  8. Java进阶1. Synchronized 关键字

    Java进阶1. Synchronized 关键字 20131025 1.关于synchronized的简介: Synchronized 关键字代表对这个方法加锁,相当于不管那一个线程,运行到这个方法 ...

  9. VS2005 使用体验

    鄙人记性真心不好,看了就忘.此文记录下日常小工具的tips. 1)VS的小番茄: 破解版 Visual.Assist.X.V10.6.1833支持VS2010 VS2008 VS2005 VC6 破解 ...

  10. iOS 可能用到的三方框架

    1.MWPhotoBrowser 第三方图片浏览器 https://github.com/mwaterfall/MWPhotoBrowser 2.SlackTextViewController  强大 ...