我有一个与机器的通信接口,并获得了一个dll,提供了许多功能。一切正常,只要我进行沟通。如果没有什么可以沟通让我们说5分钟,那么这些功能就不再起作用了。我想这是因为它都被垃圾收集器清理干净了。经过一些研究后,我应该用GCHandle.Alloc(object, GCHandleType.Pinned);
这里有一些代码:
对象
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class DNCC_PARAM
{
public int nMacNo;
public int nOwnPort;
public int nIpAddr;
public int nNCPort;
[MarshalAsAttribute(UnmanagedType.FunctionPtr)]
public Delegate CallBackFunction;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
public short[] arrTimeout = new short[20];
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
public short[] arrRetry = new short[20];
}
某些dll导入
[DllImport(@"path to dll", CharSet = CharSet.Ansi)]
public static extern int Initialize([In()] DNCC_PARAM dncPara);
[DllImport(@"path to dll", CharSet = CharSet.Ansi)]
private static extern int dncc_Connect(int hdl);
[DllImport(@"path to dll", CharSet = CharSet.Ansi)]
private static extern int dncc_Disconnect(int hdl);
对象的实例
DNCC_PARAM param = new DNCC_PARAM();
初始化沟通
// fill the object with some data
param.nMacNo = 1;
param.nOwnPort = 7005;
param.nIpAddr = (int)IPAddress.Parse("192.168.0.10").Address;
param.nNCPort = 7005;
param.CallBackFunction = new TypeOfCallBackFunction(AppCallBack);
// init the communication
nDNCC_HANDLE = Initialize(param);
回调函数
private void AppCallBack(int iHandle, int iEvent, IntPtr arg)
{
// doing some stuff here
}
因此,当我尝试将对象固定为GCHandle.Alloc(param, GCHandleType.Pinned);
时,我会收到一条消息,指出该对象不包含原始数据。如何防止GC清除对象?
我当前的“解决方案”是一个计时器,它会在每分钟左右进行一些通信。我的工作,但我觉得很难看。
答案 0 :(得分:0)
我认为您正在寻找Marshal.StructureToPtr
。在这里,您分配的托管对象的内存布局与您尝试通过MarshalAs
属性描述的非托管布局相对应。因此,您需要Marshal
类来创建具有所需布局的结构的非托管副本。
GCHandle
只能在托管和非托管内存布局相同时使用,因此可以使用相同的内存。