C#:通过引用将其他参数传递给委托

时间:2020-04-15 10:04:03

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

我目前正试图极大地优化程序的运行时,偶然发现以下问题。

问题

在某些时候,我必须从EnumWindows(请参阅Microsoft Docs)中调用user32.dll,定义如下:

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引用到用作代理的函数中?有这种方法的替代方法吗?

该解决方案应具有高性能(第一要务)且可维护。

1 个答案:

答案 0 :(得分:1)

您可以为此使用BigInt。实际上,GCHandle给出了您要尝试执行的操作的示例。

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();
}
相关问题