【问题标题】:C#: Pass additional argument to delegate by referenceC#:通过引用将附加参数传递给委托
【发布时间】:2020-07-28 06:23:15
【问题描述】:

我目前正在尝试大量优化程序的运行时,偶然发现了以下问题。

问题

有时我必须从user32.dll 调用EnumWindows(参见Microsoft Docs),定义如下所示:

internal static class NativeMethods
{
    public delegate bool EnumWindowsProc(IntPtr hWnd, int lParam);

    [DllImport("user32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool EnumWindows(EnumWindowsProc enumFunc, IntPtr lParam);
    //...
}

如您所见,我通过一个委托对每个窗口执行操作。

我这样称呼这个方法:

NativeMethods.EnumWindows(GetVisibleWindowDelegate, IntPtr.Zero);

private bool GetVisibleWindowDelegate(IntPtr windowHandle, int _)

注意:我没有在委托中使用int 参数,因此没有使用名称。

这很好用。现在进行优化:我必须访问和存储多个类型的动态列表 List<IntPtr>IDictionary<int, Rectangle> 包装在一个名为 RuntimeInformation 的对象中,跨越各种类中的多个方法。

从这个 RuntimeInformation 对象来回复制值会在我的硬件上为每个方法调用使用大约 20 毫秒的宝贵运行时间。这就是为什么我想通过引用传递这个对象,但我无法将引用传递给我的GetVisibleWindowDelegate

接近

我无法更改委托类型,因为我无法控制调用它。

如果我尝试像这样调用EnumWindows

NativeMethods.EnumWindows(
    (windowHandle, _) => GetVisibleWindowDelegate(windowHandle, ref runtimeInformation),
    IntPtr.Zero
);

我得到了错误

Error CS1628  Cannot use ref, out, or in parameter 'runtimeInformation' inside an anonymous method, lambda expression, query expression, or local function

据我所知,引用的类属性不存在。

问题

如何将我的RuntimeInformation 引用到我用作委托的函数中?这种方法有替代方案吗?

解决方案应该具有高性能(第一优先级)并且可维护。

【问题讨论】:

    标签: c# optimization delegates pass-by-reference


    【解决方案1】:

    您可以为此使用GCHandle。事实上,docs for GCHandle.Alloc 有一个例子说明你正在尝试做什么。

    private static bool GetVisibleWindowDelegate(IntPtr windowHandle, IntPtr lparam)
    {
        var handle = GCHandle.FromIntPtr(lparam);
        var runtimeInformation = (RuntimeInformation)handle.Target;
    
        // ...
    }
    
    
    RuntimeInformation runtimeInformation = ...
    
    var handle = GCHandle.Alloc(runtimeInformation);
    try
    {
        var callback = new EnumWindowsProc(GetVisibleWindowDelegate);
        NativeMethods.EnumWindows(callback, GCHandle.ToIntPtr(handle));
    }
    finally
    {
        handle.Free();
    }
    

    【讨论】:

      猜你喜欢
      • 2012-07-12
      • 2016-09-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-07
      • 1970-01-01
      • 1970-01-01
      • 2018-03-26
      相关资源
      最近更新 更多