• C#中委托和代理的深刻理解(转载)


    在写代码的过程中遇到了一个问题,就是“

    .net CallbackOnCollectedDelegate 垃圾回收问题。

    QQ截图20150618172140

    使用全局钩子的时候出现:

    globalKeyboardHook+keyboardHookProc::Invoke”类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃、损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们。

    所以,有人建议不要直接传入委托,而是把委托赋值给类的成员变量。这样子就不会导致垃圾回收的时候把委托变量给销毁的情况发生。

    一、代理

    首先我们要弄清代理是个什么东西。别让一串翻译过来的概念把大家搞晕了头。
    有的文章把代理称委托、代表等,其实它们是一个东西,英文表述都是“Delegate”。由于没有一本权威的书来规范这个概念,所以现在网上对它的称谓不一。本文我将以“代理”来称谓Delegate。
    代理是什么呢?我认为“代理就是用来定义指向方法的引用”。下面我们就通过类来理解代理。
    如:
    Ren r = new Ren("车延禄");
    上面的代码,就是使用Ren这个类定义了一个指“车延禄”这个对象实例的一个引用。
    也可以这样理解:用Ren类定义的变量r,指向一个“车延禄”对象的实例。
    类所定义的变量指向的是一个对象,代理所定义的变量指向的是个方法,当然这个方法可以是静态方法也可以是实例方法。对代理引用的调用就是对代理所指向方法的调用。
    1.代理声明的语法:
    [public/private] delegate <返回值类型> <代理名称>(<参数列表>);
    [public/private]:访问修饰符。
    delegate:代理声明关键定,相当于类声明的Class关键定
    <返回值类型>:代理所指向的方法的返回值类型
    <代理名称>:代理类型的名称
    <参数列表>:代理所的指向的方法的参数列表。
    要想使代理对象能够指向一个方法,那这个方法的要满足两个条件
    a.方法返回类型要与delegate声明中的“返回值类型”一致。
    b.方法的形参形表要与delegate声明中的“参数列表”一致。
    如:
    delegate void MyDelegate(string str,int index);
    该代理声明表示:该代理指向的方法必须是返回空类型,并且拥有两个参数,第一个是字符串类型,第二个是整型。
    2.代理“实例化”:
    代理声明相当于类的定义。有了类的定义后我们要还需生成这个类的对象;同样有了代理的声明我们还需要“实例化”代理
    如:MyDelegate md = new MyDelegate(Show);
    这里的md就是代理变量。在代理的“实例化”的时候必须在构造函数中传入一个方法名。这个方法名就是该代理指向的方法,当然该方法的返回值类型与参数类型一定要与代理的声明一致。
    Show方法定义如下:
    public static void Show(string str, int index)
    {
    Console.WriteLine("Show"+str+index.ToString());
    }
    3.代理的调用:
    md("hello world",22);
    此时调用的就是md这个代理变量所指向的Show方法。
    4.例子:
    delegate void MyDelegate(string str,int index);    //声明代理
    class Test
    {
    public static void Show(string str, int index)     //声明方法
    {
    Console.WriteLine("Show"+str+index.ToString());
    }
    public static void Main(string[] args)
    {
    MyDelegate md = new MyDelegate(Show); //1.实例化代理,传入方法
    md("hello world",22);                                    //2.传入参数
    }
    }
    5.代理的应用:
    代理的主要应用就是在DotNet中的事件处理,所以要想研究事件我们必须要理解代理的概念。有的文章使用代理进行冒泡排序,我感觉这没必要,因为不用代理我也可以排序,更况且在C#语法中也不需要我们手动编写冒泡排序代码。
    关于代理,大家要理解代理是个什么东西,并且能够写一个简单的代理示例就可以了。

    但是在我这个案例中,按照上面的方法尝试还是会出现委托被垃圾回收的情况。帖子的详细地址:http://www.sufeinet.com/forum.php?mod=redirect&goto=findpost&ptid=12492&pid=74262

    最后是在国外的一个论坛,老外给出了最终的答案,具体的原因分析请查看帖子5楼给出的英文地址详情分析。http://stackoverflow.com/questions/9957544/callbackoncollecteddelegate-in-globalkeyboardhook-was-detected

  • 相关阅读:
    20171017/20171018
    BZOJ[3193] [JLOI2013]地形生成
    BZOJ[1009] [HNOI2008]GT考试
    BZOJ[4767] 两双手
    BZOJ[4013] [HNOI2015]实验比较
    BZOJ[1925] [Sdoi2010]地精部落
    20171015 杂题
    20171015
    20171014
    USACO 2015 December Contest, Gold Problem 3. Bessie's Dream
  • 原文地址:https://www.cnblogs.com/caianhua/p/4587494.html
Copyright © 2020-2023  润新知