代码改变世界

销毁COM对象引用时内存异常。(未释放资源导致)

  沐海  阅读(484)  评论(0编辑  收藏  举报
public void   Disp(){
       Dispose(true);
       }
 
       /// <summary>
       /// 销毁
       /// </summary>
       /// <param name="disposing"></param>
       protected override void Dispose(bool disposing)
       {
           try
           {
               if (disposing)
               {
                   graphState = State.Stopped;
 
 
                   if (mediaCtrl != null && mediaCtrl1 != null)
                   {
                       mediaCtrl.Stop();
                       mediaCtrl1.Stop();
 
                   }
                   Marshal.ReleaseComObject(mediaCtrl);
                   Marshal.ReleaseComObject(mediaCtrl1);
 
 
                   mediaCtrl = null;
                   mediaEvt = null;
                   videoWin = null;
 
                   mediaCtrl1 = null;
                   mediaEvt1 = null;
                   videoWin1 = null;
 
                   if (canStep)
                   { frameStep = null; frameStep1 = null; }
                   
                   if (graphBuilder != null)
                       Marshal.ReleaseComObject(graphBuilder);
                   if (graphBuilder1 != null)
                       Marshal.ReleaseComObject(graphBuilder1);
                   graphBuilder = null; graphBuilder1 = null;
 
                panel1.Dispose();
                  panel2.Dispose();
                   //panel1 = null;
                   //panel2 = null;
                  trackBar1.Dispose();
                   //trackBar1 = null;
                   fName = null;
                   fName1 = null;
 
 
 
 
               }
               base.Dispose(disposing);
           }
           catch { }
       }


这是一个销毁方法。重点在于

Marshal 类

提供了一个方法集,这些方法用于分配非托管内存、复制非托管内存块、将托管类型转换为非托管类型,此外还提供了在与非托管代码交互时使用的其他杂项方法。

命名空间:  System.Runtime.InteropServices
程序集:  mscorlib(在 mscorlib.dll 中)

Marshal 类中定义的 static 方法对于处理非托管代码至关重要。此类中定义的大多数方法通常由需要在托管和非托管编程模型之间提供桥梁的开发人员使用。例如,StringToHGlobalAnsi 方法将 ANSI 字符从指定的字符串(在托管堆中)复制到非托管堆中的缓冲区。该方法还分配大小正确的目标堆。

当然你也可以直接从非托管的WIN API 来创建INVOKE程序。(通常也是这么使用的)

 

这里使用的

Marshal.ReleaseComObject 方法

递减所提供的运行库可调用包装的引用计数。

 
 
C#
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public static int ReleaseComObject(
	Object o
)

参数

o
类型:System..::.Object

要释放的 COM 对象。

返回值

类型:System..::.Int32

o 关联的运行库可调用包装的引用计数的新值。此值通常为零,因为无论调用包装 COM 对象的托管客户端有多少,运行库可调用包装仅保留对该对象的一次引用。

 

每当 COM 接口指针进入公共语言运行库时,该指针都包装在运行库可调用包装中。如果您不熟悉此包装的功能,请参见 运行库可调用包装

此方法用于显式控制从托管代码使用的 COM 对象的生存期。应及时(或者在对象按指定的顺序必须释放时)使用此方法,来释放引用某些资源的基础 COM 对象。

该运行库可调用包装具有引用计数,每次将 COM 接口指针映射到该运行库可调用包装时,此引用计数都将递增。ReleaseComObject 方法递减运行库可调用包装的引用计数。当引用计数达到零时,运行库将释放非托管 COM 对象上的所有引用,并在您试图进一步使用该对象时引发 System..::.NullReferenceException。如果从非托管代码向托管代码传递同一 COM 接口的次数超过一次,则包装上的引用计数将依次递增,而且调用 ReleaseComObject 将返回剩余引用的数目。

注意注意:

若要确保释放运行库可调用包装及原始 COM 对象,可构造一个循环,并从该循环调用此方法,直到引用计数达到零。

注意注意:

此方法使用 SecurityAction..::.LinkDemand 防止不可信代码对它进行调用;只有直接调用方才需要具有 SecurityPermissionAttribute..::.UnmanagedCode 权限。如果您的代码可从部分受信任的代码调用,则未经验证不要将用户输入传递给 Marshal 类方法。有关使用 LinkDemand 成员的重要限制,请参见 Demand 和 LinkDemand

“折叠”图像权限

编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述
记录生活、工作、学习点滴!
E-Mail:mahaisong@hotmail.com 欢迎大家讨论。
沐海博客园,我有一颗,卓越的心!
点击右上角即可分享
微信分享提示