我已经用C#封装了一个用C编写的dll。它在几次迭代中都可以正常工作,直到我收到“在垃圾回收委托上进行了回调”
我已经做了网上提到的所有修改。回调清理是静态的,以防止无法成功收集它。 还尝试了GCHandle.Alloc函数,但未成功。 这是我在C#中代码的一部分。
有人可以提出另一种想法如何防止其移动吗?
我已经采取了一种解决方法,并且每次都设置一次回调(不在下面的代码中),这使问题消失了,但是我不喜欢这种解决方案。
谢谢
罗伊
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Net;
using System.Net.Sockets;
using AutomatedTestStation.Connection;
using System.Security.Permissions;
namespace Control
{
public delegate int TransmitBuffer(IntPtr buffer, int len);
public delegate void RegisterMessageRecieved(IntPtr register);
public class WarrperApi
{
public const string DLL_LOCATION = @"DriverDll.dll";
[DllImport(DLL_LOCATION, SetLastError = true)]
public static extern int Init(TransmitBuffer transmitBuffer,
RegisterMessageRecieved registerMsgRecieved,
byte[] rxBuffer, int rxlength);
[DllImport(DLL_LOCATION, SetLastError = true)]
public static extern void RegisterWrite(UInt16 chipId, UInt16 address, UInt32 value);
[DllImport(DLL_LOCATION, SetLastError = true)]
public static extern void RegisterRead(UInt16 chipId, UInt16 address);
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct Register
{
public UInt16 header;
public UInt16 cmd;
public UInt32 length;
public UInt32 time;
public byte mode;
public UInt16 id;
public UInt16 bitmap;
public UInt16 reg_index;
public UInt32 write_val;
public UInt32 read_val;
public byte crc;
}
/*following decleration purpose is to prevent delgates from being destroyed by garbage collector*/
private static TransmitBuffer transmitBuffer = new TransmitBuffer(TransmitBufferCb);
private static RegisterMessageRecieved registerMessageRecieved = new RegisterMessageRecieved(RegisterMsgRecievedCb) ;
private static GCHandle gchTransmitBuffer;
private static GCHandle gchRegisterMessageRecieved;
WarrperApi( TcpClientConnection _tcpClientConnection,IListener _listener)
{
tcpClientConnection = _tcpClientConnection;
listener = _listener;
gchTransmitBuffer = GCHandle.Alloc(transmitBuffer);
gchRegisterMessageRecieved = GCHandle.Alloc(registerMessageRecieved);
Init(TransmitBufferCb,RawMsgRecievedCb, buffer, BUFFER_SIZE);
}
private static int TransmitBufferCb(IntPtr ptr, int len)
{
byte[] buffer = new byte[len];
Marshal.Copy(ptr, buffer, 0, len);
lock(tcpClientConnection)
{
tcpClientConnection.Write(buffer, 0, len);
}
return 1;
}
private static void RegisterMsgRecievedCb(IntPtr _reg)
{
Register reg = new Register();
reg = (Register)Marshal.PtrToStructure(_reg, typeof(Register));
listener.OnRegisterMessageRecived(reg);
}
public void SetRegister(ushort chipId, ushort address, uint value )
{
RegisterWrite(chipId, address, value);
}
public void GetRegister(ushort chipId, ushort address)
{
try
{
RegisterRead(chipId, address);
}
catch(Exception ex)
{
throw new Exception("");
}
}
}
}