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

.net CallbackOnCollectedDelegate 垃圾回收问题。

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

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

C#中委托和代理的深刻理解(转载)的更多相关文章

  1. C# 中委托和代理是一个概念吗??

    刚刚看了一下资料,发现有些资料说的是代理,有的说是委托,但都是指同一样东西delegate,委托和事件是有关的,因为事件的本质就是多播委托,关于多播委托楼主可以找找资料就知道了. 不过个人觉得这两个概 ...

  2. 关于c#中委托与事件的一些理解

    文章目的:作者(初学者)在学习c#的过程中,对事件.委托及其中的“object sender,EventArgs e”一直感觉理解不透,因此在网上找了一些资料,学习并整理出了该篇笔记,希望能将自己的心 ...

  3. Nodejs第一天-{Nodejs基础 深刻理解浏览器 环境变量 基础语法}

    Nodejs第一天 1.什么是Nodejs ​ Nodejs是一个可以运行(解析)ECMAScript的环境; ​ ECMAScript是规定了一些列的语法 ,这些语法想要解析的执行就需要放在某个环境 ...

  4. 十分钟理解Java中的动态代理

    十分钟理解 Java 中的动态代理   一.概述 1. 什么是代理 我们大家都知道微商代理,简单地说就是代替厂家卖商品,厂家“委托”代理为其销售商品.关于微商代理,首先我们从他们那里买东西时通常不知道 ...

  5. 深刻理解:C#中的委托、事件

    C#中的事件还真是有点绕啊,以前用JavaScript的我,理解起来还真是废了好大劲!刚开始还真有点想不明白为什么这么绕,想想和JS的区别,最后终于恍然大悟! C#中事件绕的根本原因: C#的方法,它 ...

  6. 深刻理解Java中final的作用(一):从final的作用剖析String被设计成不可变类的深层原因

    声明:本博客为原创博客,未经同意,不得转载!小伙伴们假设是在别的地方看到的话,建议还是来csdn上看吧(原文链接为http://blog.csdn.net/bettarwang/article/det ...

  7. JavaScript中事件委托(事件代理)详解

    在JavaScript的事件中,存在事件委托(事件代理),那么什么是事件委托呢? 事件委托在生活中的例子: 有三个同事预计会在周一收到快递.为签收快递,有两种办法:一是三个人在公司门口等快递:二是委托 ...

  8. [转]深刻理解Python中的元类(metaclass)以及元类实现单例模式

    使用元类 深刻理解Python中的元类(metaclass)以及元类实现单例模式 在看一些框架源代码的过程中碰到很多元类的实例,看起来很吃力很晦涩:在看python cookbook中关于元类创建单例 ...

  9. Js 中的事件委托/事件代理

    什么叫事件委托/事件代理呢 ? JavaScript高级程序设计上讲:事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件.   事件冒泡: 当事件发生后,这个事件就要开始传 ...

随机推荐

  1. drupal node机制理解

    [1]根据结构的功能结构的不同,drupal划分为,node,user,comment等不同的结构,他们的结构是不同的.他们可以作为四个不同的抽象类,根据这个抽象类,分别有一套hook函数去控制实现的 ...

  2. 原生js获取手机定位信息

    <script type="text/javascript"> function Location() {}; Location.prototype.getLocati ...

  3. js实现图片延时加载的原理

    实现原理: 附:(http://www.cnblogs.com/fishtreeyu/archive/2011/03/12/1982067.html) 把所有需要延时加载的图片改成如下的格式: < ...

  4. Java设计模式—责任链模式

    责任链模式的定义: 使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止. 责任链模式的重点是在"链& ...

  5. 《ArcGIS Runtime SDK for Android开发笔记》——数据制作篇:紧凑型切片制作(Server缓存切片)

    1.前言 在ArcGIS 10中出现了一种新的切片缓存文件格式:紧凑型存储(Compact).与之前的松散型存储(Exploded)相比,它有迁移方便.创建更快.减少存储空间等诸多优点,已经成为了现在 ...

  6. hibernate 一览表

  7. Sticky footers 套路

    [CSS Secrets] http://shop.oreilly.com/product/0636920031123.do 以饿了么商家信息的弹出层为例,布局如下: <!-- 饿了么 弹出层部 ...

  8. spring boot拦截器配置

    1.在spring boot配置文件application.properties中添加要拦截的链接 com.url.interceptor=/user/test 2.编写拦截器代码 ,创建UrlInt ...

  9. 『看球笔记』20131230切尔西vs利物浦,赛后复盘聊聊球

    2013-12-30 第十九轮英超联赛 切尔西vs利物浦         看着这张板凳合照… 有木有一种心里哇凉哇凉的感觉.   赛后whoscored的平均位置图 左边车子,右边我军     阿格回 ...

  10. IOS Runtime的用法

    什么是runtime? 1> runtime是一套底层的C语言API(包含很多强大实用的C语言数据类型.C语言函数)2> 实际上,平时我们编写的OC代码,底层都是基于runtime实现的* ...