怎么样使用.NET回调函数?
怎么样使用.NET回调函数?
[文章来源:.NET SDK文档]
回调函数是托管应用程序中可帮助非托管 DLL 函数完成任务的代码。对回调函数的调用将从托管应用程序中,通过一个 DLL 函数,间接地传递给托管实现。在用平台调用调用的多种 DLL 函数中,有些函数要求正确地运行托管代码中的回调函数。本主题将介绍托管函数的元素,并说明如何实现回调函数和从托管代码中调用回调函数。
回调函数基础
要从托管代码中调用大多数 DLL 函数,可创建该函数的托管定义,然后调用该函数。此过程比较直接。
要使用需要回调函数的 DLL 函数,则会有一些附加的步骤。首先,必须在文档中查阅该函数,确定该函数是否需要回调。接着,必须在托管应用程序中创建回调函数。最后,调用该 DLL 函数,并将指向回调函数的指针当作参数进行传递。下图总结了这些步骤。
回调函数和实现
回调函数非常适合在重复执行任务的情况下使用。另一个常见用途是与枚举函数(如 Win32 API 中的 EnumFontFamilies、EnumPrinters 和 EnumWindows)一起使用。如下一节中的示例所示,EnumWindows 函数将枚举计算机上的所有现有窗口,并调用回调函数来对每个窗口执行一项任务。
实现回调函数
以下过程将说明托管应用程序如何使用平台调用来输出本地计算机上每个窗口的句柄值。尤其是,示例将使用 EnumWindows 函数来逐步浏览窗口列表,并使用一个托管回调函数(名为 CallBack)来输出窗口句柄的值。
实现回调函数
开始实现之前,先查看 EnumWindows 函数的签名。EnumWindows 具有以下签名:
BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam)
表示此函数需要回调的线索之一是存在 lpEnumFunc 参数。如果参数采用指向回调函数的指针,其名称中通常会有 lp(长指针)前缀与 Func 后缀的组合。有关 Win32 函数的文档,请参见 Microsoft Platform SDK。
创建托管回调函数。该示例声明一个名为 CallBack 的委托类型,此委托类型采用两个参数:hwnd 和 lparam。第一个参数是窗口的句柄;第二个参数由应用程序定义。在此版本中,这两个参数都必须是整数。
回调函数通常会返回非零值来表示成功,返回零来表示失败。本示例将返回值显式设置为 true,以继续进行枚举。
创建一个委托,并将其作为参数传递给 EnumWindows 函数。平台调用会自动将委托转换为常见的回调格式。
确保在回调函数完成其工作之前,垃圾回收器不会回收委托。如果委托作为参数进行传递,或者所包含的委托作为结构中的字段进行传递,则该委托在调用期间不会被回收。因此,正如下面的枚举示例所示,回调函数会在调用返回前完成其工作,而无需托管调用方执行额外的操作。
然而,如果可以在调用返回后调用回调函数,则托管调用方必须采取相应的措施来确保委托在回调函数完成其工作之前不会被回收。有关防止垃圾回收的详细信息,请参见用平台调用进行 Interop 封送处理。
示例
[Visual Basic]
Imports System
Imports System.Runtime.InteropServices
Public Delegate Function CallBack( _
hwnd As Integer, lParam As Integer) As Boolean
Public Class EnumReportApp
Declare Function EnumWindows Lib "user32" ( _
x As CallBack, y As Integer) As Integer
Public Shared Sub Main()
EnumWindows(AddressOf EnumReportApp.Report, 0)
End Sub 'Main
Public Shared Function Report(hwnd As Integer, lParam As Integer) _
As Boolean
Console.Write("Window handle is ")
Console.WriteLine(hwnd)
Return True
End Function 'Report
End Class 'EnumReportApp
[C#]
using System;
using System.Runtime.InteropServices;
public delegate bool CallBack(int hwnd, int lParam);
public class EnumReportApp {
[DllImport("user32")]
public static extern int EnumWindows(CallBack x, int y);
public static void Main()
{
CallBack myCallBack = new CallBack(EnumReportApp.Report);
EnumWindows(myCallBack, 0);
}
public static bool Report(int hwnd, int lParam) {
Console.Write("Window handle is ");
Console.WriteLine(hwnd);
return true;
}
}