.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;
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章