dllImport回调函数丢失(垃圾收集器)

时间:2018-08-19 10:25:38

标签: garbage-collection delegates native dllimport unmanaged

我已经用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("");
            }
        }
    }
}

0 个答案:

没有答案