PInvoke的回调非常缓慢
本文关键字:缓慢 非常 回调 PInvoke | 更新日期: 2023-09-27 18:20:31
我在C#应用程序中使用本机/非托管C++DLL。我使用PInvoke:调用本机函数在C#中注册回调方法
[DllImport("MyHook.dll", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.U1)] // necessary due to http://dotnet.dzone.com/articles/pinvoke-c-bool-return-values
private static extern bool InstallHook(CallbackPrototype callback);
private delegate int CallbackPrototype(byte* bytes, int size, int max);
// ...
var callback = new CallbackPrototype(MyCallback);
_callbackHandle = GCHandle.Alloc(callback);
var result = InstallHook(callback);
// somewhere when I'm removing the hook, I call _callbackHandle.Free();
然后,当事件发生时,本机C++DLL会调用我的回调。
private int MyCallback(byte* bytes, int size, int max)
{
//var buffer = new byte[size]; // A
//Marshal.Copy(new IntPtr(bytes), buffer, 0, size); // B
//WrapperInstance.ParseBytes(buffer, 0, size); // C
var x = 1 + 1; // D
return size;
}
当所有内容都被注释掉时,效果很好。如果我开始在回调中取消对行A的注释,它会变得非常慢。我注意到了这一点,因为回调是在关键时刻调用的。回调运行时持续时间太长以至于我作为一个人注意到了这一点,这是不可接受的。
这怎么会发生?size参数仅从1到100。这最多只需要分配100个字节,对于今天的计算机来说很少。我需要改进以使回调的运行时间更快。有什么想法吗?
为了进一步测试,我添加了D行。这没有任何影响。
编辑:为了进行更详细的测试,我在创建类时分配了一个大的缓冲区。因此,行A不再在回调中。如果B行被注释掉,它突然又开始花费大量时间。这一定与托管代码/虚拟机有关。我希望有可能使它更快。
您基本上要做的是将字节复制到缓冲区中,然后进行解析。你可以一次完成,就像这样:
var bytes = ReadBytes(address, Marshal.SizeOf(typeof(T)), isRelative);
fixed (byte* b = bytes)
return (T) Marshal.PtrToStructure(new IntPtr(b), typeof (T));
我从我的内存库中取了这个例子,我认为它会比你现在使用的代码快很多,假设你只尝试检索值类型。