做项目的时候遇到了这个问题:

检测到:CallbackOnCollectedDelegate

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

callbackOnCollectedDelegate MDA

.NET Framework 4

如果将一个委托作为函数指针从托管代码封送到非托管代码,并且在对该委托进行垃圾回收后对该函数指针发出了一个回调,则将激活 callbackOnCollectedDelegate 托管调试助手 (MDA)。

症状

尝试通过从托管委托获取的函数指针调入托管代码时发生访问冲突。 这些故障虽然不是公共语言运行时 (CLR) bug,但是会显示为公共语言运行时 bug,因为 CLR 代码中发生了访问冲突。

此故障的具体情况并非千篇一律:有时对函数指针发出的调用可以成功,有时却会失败。 仅在负载过大或按随机次数进行尝试时会发生此故障。

原因

从其创建函数指针并将创建的函数指针公开给非托管代码的委托已被垃圾回收。 当非托管组件尝试对该函数指针发出调用时,会产生访问冲突。

该故障是随机出现的,因为它的出现取决于垃圾回收发生的时间。 如果某个委托符合回收条件,则会在回调之后进行垃圾回收,并且调用会成功。 在其他一些情况下,垃圾回收发生在回调之前,回调会引发访问冲突,并且程序会停止。

该故障发生的可能性取决于从封送委托到对函数指针发出回调之间的时间以及垃圾回收的频率。 如果从封送委托到接着发生的回调之间的时间很短,则发生该故障会的机会就很少。 通常情况下,如果接收函数指针的非托管方法没有保存该函数指针以备以后使用,而是立即对函数指针发出回调以便在返回之前完成其操作,就很少发生这种故障。 同样道理,系统负载过大时会发生更多垃圾回收,进而使得垃圾回收更有可能在回调之前发生。

解决方法

一旦将委托作为非托管函数指针封送出去,垃圾回收器就无法跟踪其生存期。 这样,在该非托管函数指针的生存内,您的代码必须保持一个指向该委托的引用。 但是在此之前,您首先必须确定回收了哪个委托。 激活 MDA 之后,MDA 会提供该委托的类型名称。 请使用此名称在您的代码中搜索将该委托外传给非托管代码的平台调用或 COM 签名。 通过这些调用站点之一将有问题的委托传递出去。 您还可以启用 gcUnmanagedToManaged MDA 以强制在每次向运行时发出回调之前都进行垃圾回收。 这样可以确保在回调之前总是进行垃圾回,从而可以消除由垃圾回收引起的不确定性。 一旦您得知回收了哪个委托,请更改您的代码,以便在封送的非托管函数指针的生存期内在托管端保持对该委托的引用。

看了一会,也不是很清楚,大致知道它是因为委托在回调之前已经被回收了,看了网上一片资料,了解到,解决此问题的方法就是扩大委托的作用域,向非托管函数传递委托的引用。参考资料:http://blog.chinaunix.net/uid-22695386-id-3040624.html
具体到代码中的解决方式就是:
Win32Lib.cs
 using System;
 using System.Collections.Generic;
 using System.Text;
 using System.Runtime.InteropServices;

 namespace testNotifyIcon
 {
     #region 委托

     internal delegate int HookProc(int code, int wParam, IntPtr lParam);//声明委托

     #endregion

     //略去若干行代码

     /// <summary>
     /// Win32函数库(仅摘录用到的函数)
     /// </summary>
     internal static class Win32Lib
     {
         #region 字段
         public static HookProc hookproc;//这里是重点

         public const string ATOM_FLAG = "HookSysKey";
         public const string SHELL_FALG = "Winlogon";
         ;    //注入代码所占的双字数
         );    //字节数
         ;         //注入代码线程函数偏移量
         public const UInt32 TOKEN_ADJUST_PRIVILEGES = 0x0020;
         public const UInt32 TOKEN_QUERY = 0x0008;
         public const UInt32 SE_PRIVILEGE_ENABLED = 0x00000002;
         public const string SE_DEBUG_NAME = "SeDebugPrivilege";
         ;

         #endregion

         #region 外部函数

         #region user32.dll

         [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
         public static extern IntPtr SetWindowsHookEx(int hookType, HookProc lpfn, IntPtr pInstance, int threadId);

         [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
         public static extern bool UnhookWindowsHookEx(IntPtr pHookHandle);

         [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
         public static extern int CallNextHookEx(IntPtr pHookHandle, int nCode, int wParam, IntPtr lParam);

         [DllImport("user32.dll")]
         public static extern bool BlockInput(bool fBlockIt);

         #endregion

         //此处略图N行代码

         #endregion
     }
 }

InputHook.cs

 //略去N行代码
 IntPtr pInstance = Win32Lib.GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
 Win32Lib.hookproc = new HookProc(LowLevelKeyboardProc);//此为重点
 //安装钩子
 m_lHookID = Win32Lib.SetWindowsHookEx(
   (int)HookType.WH_KEYBOARD_LL,
   Win32Lib.hookproc,//此为重点
   pInstance,
   );
 //略去N行代码

重点就是这样

 internal delegate int HookProc(int code, int wParam, IntPtr lParam);
 public class test
 {
     private static HookProc hookproc;
     hookproc =  new HookProc(xxx);
     SetWindowsHookEx(,hookproc ,     Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[]), );
 }

C#问题记录-CallbackOnCollectedDelegate的更多相关文章

  1. 记一次debug记录:Uncaught SyntaxError: Unexpected token ILLEGAL

    在使用FIS3搭建项目的时候,遇到了一些问题,这里记录下. 这里是发布搭建代码: // 代码发布时 fis.media('qa') .match('*.{js,css,png}', { useHash ...

  2. nginx配置反向代理或跳转出现400问题处理记录

    午休完上班后,同事说测试站点访问接口出现400 Bad Request  Request Header Or Cookie Too Large提示,心想还好是测试服务器出现问题,影响不大,不过也赶紧上 ...

  3. Kali对wifi的破解记录

    好记性不如烂笔头,记录一下. 我是在淘宝买的拓实N87,Kali可以识别,还行. 操作系统:Kali 开始吧. 查看一下网卡的接口.命令如下 airmon-ng 可以看出接口名称是wlan0mon. ...

  4. 2015 西雅图微软总部MVP峰会记录

    2015 西雅图微软总部MVP峰会记录 今年决定参加微软MVP全球峰会,在出发之前本人就已经写这篇博客,希望将本次会议原汁原味奉献给大家 因为这次是本人第一次写会议记录,写得不好的地方希望各位园友见谅 ...

  5. 分享一个SQLSERVER脚本(计算数据库中各个表的数据量和每行记录所占用空间)

    分享一个SQLSERVER脚本(计算数据库中各个表的数据量和每行记录所占用空间) 很多时候我们都需要计算数据库中各个表的数据量和每行记录所占用空间 这里共享一个脚本 CREATE TABLE #tab ...

  6. 我是如何在SQLServer中处理每天四亿三千万记录的

    首先声明,我只是个程序员,不是专业的DBA,以下这篇文章是从一个问题的解决过程去写的,而不是一开始就给大家一个正确的结果,如果文中有不对的地方,请各位数据库大牛给予指正,以便我能够更好的处理此次业务. ...

  7. 前端学HTTP之日志记录

    前面的话 几乎所有的服务器和代理都会记录下它们所处理的HTTP事务摘要.这么做出于一系列的原因:跟踪使用情况.安全性.计费.错误检测等等.本文将谥介绍日志记录 记录内容 大多数情况下,日志的记录出于两 ...

  8. ASP.NET Core应用中如何记录和查看日志

    日志记录不仅对于我们开发的应用,还是对于ASP.NET Core框架功能都是一项非常重要的功能特性.我们知道ASP.NET Core使用的是一个极具扩展性的日志系统,该系统由Logger.Logger ...

  9. python+uwsgi导致redis无法长链接引起性能下降问题记录

    今天在部署python代码到预生产环境时,web站老是出现redis链接未初始化,无法连接到服务的提示,比对了一下开发环境与测试环境代码,完全一致,然后就是查看各种日志,排查了半天也没有查明是什么原因 ...

随机推荐

  1. 哪个U盘启动工具能安装红帽系统,

    安装红帽子,不要使用windows系统下的PE启动盘,两者引导方式不一样,不通用的.正确的方法是网上下载红帽子的ISO镜像文件后,用UltraISO这个工具写入优盘或者光盘,得到的系统盘才可以启动电脑 ...

  2. Umbraco项目发布错误 --More than one type want to be a model for content type authorize

    在开发项目时,解决方案下面包括三个项目 MyUmbracoProject MyUmbracoProject.Core MyUmbracoProject.FrontEnd 第一个项目MyUmbracoP ...

  3. Sharepoint2013商务智能学习笔记之部署AdventureWorksDW2012数据库(三)

    AdventureWorksDW2012是sql server2012的样本数据库,后面做商务智能Demo会用到,所以需要下载并安装到sql server2012上,下载地址 第一步,下载数据库 第二 ...

  4. 聊聊 CDN 缓存与浏览器缓存

    CDN 是互联网上内容分发的重要一环.无论您之前是否了解过 CDN,其实它已经在您的日常生活中发挥作用了.比如您正在淘宝挑选心仪的商品,或者在观看一段令人捧腹的视频,以及您正在阅读的这篇文章,这些资源 ...

  5. [CentOS7] 增加yum源

    下载最新rpm文件:http://fedoraproject.org/wiki/EPEL 通过源文件rpm来增加: rpm -ivh epel-release-latest-7.noarch.rpm

  6. loj#6053. 简单的函数(Min_25筛)

    传送门 题解 \(Min\_25\)筛有毒啊--肝了一个下午才看懂是个什么东西-- \(zsy\)巨巨强无敌-- //minamoto #include<bits/stdc++.h> #d ...

  7. 洛谷P5048 [Ynoi2019模拟赛]Yuno loves sqrt technology III(分块)

    传送门 众所周知lxl是个毒瘤,Ynoi道道都是神仙题 用蒲公英那个分块的方法做结果两天没卡过去→_→ 首先我们分块,预处理块与块之间的答案,然后每次询问的时候拆成整块和两边剩下的元素 整块的答案很简 ...

  8. bzoj3731: Gty的超级妹子树(树分块)

    传送门 分块树,代码参考了Manchery的 具体细节还是看代码好了 这题卡常……注意常数写好点…… //minamoto #include<iostream> #include<c ...

  9. Java Web之分页的实现(通用)

    一.用到的工具类的封装 为了实现代码的重用性,我们将经常用到的代码封装到工具类中,以便在任何地方都可以调用 1.获取路径工具 在jsp页面中,我们经常会向Servlet发送请求,并通过反射,实现通过传 ...

  10. Could not find iPhone X simulator

    Could not find iPhone X simulator Error: Could not find iPhone X simulator at resolve (/Users/zhouen ...