我目前正试图极大地优化程序的运行时,偶然发现以下问题。
问题
在某些时候,我必须从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
引用到用作代理的函数中?有这种方法的替代方法吗?
该解决方案应具有高性能(第一要务)且可维护。
答案 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();
}