日期:2014-05-18  浏览次数:21044 次

多次使用委托时被垃圾回收了,怎样解决?
用委托时又遇到问题了,代码如下:
C# code

    public partial class Form3 : Form
    {
        private static Int32 DeviceID = 0;
        private static Int32 DeviceChannel = 0;
        private static IntPtr P;
        public delegate void DataProc(Int32 ID, Int32 Channel, Int32 Value, byte keypress);

        [DllImport...)]
        public static extern byte SetCallBackProc(Int32 CallBackProc);

        private void Form3_Load(object sender, EventArgs e)
        {
            P = Marshal.GetFunctionPointerForDelegate(new DataProc(OnDataProc));
            SetCallBackProc(P.ToInt32());
        }
        
        private void OnDataProc(Int32 ID, Int32 Channel, Int32 Value, byte keypress)
        {
       ...
        }



开始运行还好,过了一会就报错:对“test!test.Form3+DataProc::Invoke”类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃、损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们。

这个问题该如何解决?

------解决方案--------------------
C# code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        DataProc DP = null; // 定义成全局
        IntPtr P = IntPtr.Zero; // 定义成全局
        
        public Form1()
        {
            InitializeComponent();

            this.Shown += new EventHandler(Form1_Shown);
        }

        void Form1_Shown(object sender, EventArgs e)
        {
            DP = new DataProc(OnDataProc);
            P = Marshal.GetFunctionPointerForDelegate(DP);

            GC.KeepAlive(DP);  // 如果不放心,在告诉垃圾回收器不要回收
            GC.KeepAlive(P);  // 如果不放心,在告诉垃圾回收器不要回收

            SetCallBackProc(P.ToInt32());
        }

        public byte SetCallBackProc(long CallBackProc) // 没有你的dll,所以这里模拟
        {
            this.Invoke(Marshal.GetDelegateForFunctionPointer(new IntPtr(CallBackProc), typeof(DataProc)),
                new Object[] { 1, 2, 500 });

            return 0;
        }

        delegate void DataProc(long ID, long Channel, long Value);

        void OnDataProc(long ID, long Channel, long Value)
        {
            double f1;
            f1 = Value / 100;

            MessageBox.Show(f1.ToString()); // 5
        }
    }
}