AE释放资源

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

.net开发Ae释放com对象的问题本文转载自:我的博文的com对象是需要释放的,不然就可能会锁住一些基础设备(如mdb文件等),这里研究了一下ae锁mdb的情况。释放方法一般是,Marshal.ReleaseComObject或Marshal.FinalReleaseComObject但要在什么时候释放com对象呢,这就需要了解dotnet跟com交互的实现方法:运行库可调用包装(RCW)。每次将COM接口指针映射到该运行时可调用包装时,此引用计数都将递增。这是msdn中Marshal.ReleaseComObject方法描述里的一句话。那这句话是什么意思呢,什么样的操作才会导致将COM接口指针映射到运行时可调用包装。做了一个简单的实验,打开一个workspace,并打开一个featureclass,使用方法Marshal.ReleaseComObject释放COM,查看引用计数(不知道如何查看引用计数,只能通过Marshal.ReleaseComObject方法),以此来判断是否执行了将COM接口指针映射到运行时可调用包操作。情况一:新声明一个workspace局部变量,将原来的workspace值赋给新变量,释放workspace,查看workspace引用计数1IWorkspaceFactorywsf=newAccessWorkspaceFactoryClass();2IWorkspacews=wsf.OpenFromFile(mdbPath,0);3IFeatureClassfls=((IFeatureWorkspace)ws).OpenFeatureClass(featureClassName);4IWorkspacews1=ws;5inti=Marshal.ReleaseComObject(ws);67//i的值为0。情况二:新声明一个workspace局部变量,通过IDataset.Workspace属性给新变量赋值,释放workspace,查看workspace引用计数1IWorkspaceFactorywsf=newAccessWorkspaceFactoryClass();2IWorkspacews=wsf.OpenFromFile(mdbPath,0);3IFeatureClassfls=((IFeatureWorkspace)ws).OpenFeatureClass(featureClassName);4IWorkspacews1=((IDataset)fls).Workspace;5inti=Marshal.ReleaseComObject(ws);6//i的值为1。我大胆的得出结论(有可能不对):将COM接口指针映射到运行时可调用包装操作是在调用执行com对象方法并返回值时才会发生。情况三:在一个方法里面打开featureclass,不释放workspace,新声明一个workspace局部变量,通过IDataset.Workspace属性给新变量负责,释放workspace,查看workspace引用计数1privateIFeatureClassgetFclss(stringpath,stringfeatureClassName)2{3IWorkspaceFactorywsf=newAccessWorkspaceFactoryClass();4IWorkspacews=wsf.OpenFromFile(path,0);5return((IFeatureWorkspace)ws).OpenFeatureClass(featureClassName);6}7IFeatureClassfls=getFclss(mdbPath,featureClassName);8IWorkspacews=((IDataset)fls).Workspace;9inti=Marshal.ReleaseComObject(ws);1011//i的值为1。情况四:跟情况三类似,不同的是调用了GC.Collect方法1IFeatureClassfls=getFclss(mdbPath,featureClassName);2GC.Collect();3IWorkspacews=((IDataset)fls).Workspace;4inti=Marshal.ReleaseComObject(ws);56//i的值为0。比较情况三跟情况四,可以得出结论,释放COM对象在dotnet中的映射对象的时候,引用计数会减一情况五:调用情况三的获取featureclass的方法,释放得到的featureclass,删除mdb文件1IFeatureClassfls=getFclss(mdbPath,featureClassName);2Marshal.ReleaseComObject(fls);3File.Delete(mdbPath);得到“文件“。。。”正由另一进程使用,因此该进程无法访问该文件。”的异常。情况六:修改getFclss方法,在方法内释放掉worksapce,再像情况五一样操作1privateIFeatureClassgetFclss(stringpath,stringfeatureClassName)2{3IWorkspaceFactorywsf=newAccessWorkspaceFactoryClass();4IWorkspacews=wsf.OpenFromFile(path,0);5try6{7return((IFeatureWorkspace)ws).OpenFeatureClass(featureClassName);8}9finally10{11Marshal.ReleaseComObject(ws);12}13}这时可以删除掉文件。情况七:调用情况六修改后的getFclss,不释放featureclass,直接删除文件1IFeatureClassfls=getFclss(mdbPath,featureClassName);2File.Delete(mdbPath);得到情况五一样的异常。情况八:调用情况六修改后的getFclss,新声明一个workspace局部变量,通过IDataset.Workspace属性给新变量赋值。1IFeatureClassfls=getFclss(mdbPath,featureClassName);2IWorkspacews=((IDataset)fls).Workspace;这时得到的ws是可以查看属性的,释放后的com对象查看属性会得到提示为“COM对象与其基础RCW分开后就不能再使用。”的异常。情况九:workspace打开ifeatureclass2次1IWorkspaceFactorywsf=newAccessWorkspaceFactoryClass();2IWorkspacews=wsf.OpenFromFile(mdbPath,0);3IFeatureClassfcls=((IFeatureWorkspace)ws).OpenFeatureClass(featureClassName);4IFeatureClassfcls1=((IFeatureWorkspace)ws).OpenFeatureClass(featureClassName);5inti=Marshal.ReleaseComObject(fcls);67//i的值为1。那么对于访问COM对象属性的属性的情况会是怎么样呢。情况十:创建getDataset方法,跟新的getFclss一样,只是返回的是IDataset,访问IDataset.Workspace,再访问IDataset.Workspace.PathName,释放workspace,查看引用计数1privateIDatasetgetDataset(stringpath,stringfeatureClassName)2{3IWorkspaceFactorywsf=newAccessWorkspaceFactoryClass();4IWorkspacews=wsf.OpenFromFile(path,0);5try6{7return((IFeatureWorkspace)ws).OpenFeatureClass(featureClassName)asIDataset;8}9finally10{11Marshal.ReleaseComObject(ws);12}13}14IDatasetds=getDataset(mdbPath,featureClassName);15IWorkspacews=ds.Workspace;16strings=ds.Workspace.PathName;17inti=Marshal.ReleaseComObject(ws);1819//i的值为1。所以,为了避免有的对象释放漏掉,最好不要使用IDataset.Workspace.PathName这种写法。/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////.net的托管并不是万能的,对于有些资源如窗体、文件、位图、数据库连接都需要相应的手动回收。.net使用的托管内存,值类型存储在堆栈上,引用类型存储在托管堆上,由GC负责垃圾回收。而COM对象使用的是内置内存,因此无法托管,需要手动释放内存。但是COM的内存管理机制是怎么样的呢?.net环境下调用COM组件,COM对象的垃圾回收应该如何进行呢,一般原则又是什么呢?这些我都不知道。于是在ArcGISEngine论坛上发帖求助,也没有人回答。现在把遇到的问题重新整理一下,发到博客园,希望能够得到解答。不管是自己还是别人帮助。也记录这个过程。一共发了三个帖子,如下:1.AE进行二次开发中,COM对象的垃圾收集问题应该如何进行?AE进行二次开发中,经常忽略的垃圾收集问题,AE是COM对象,垃圾收集问题应该如何进行?一般的for循环中的COM对象在什么时候释放了,还是自动释放?其他的情况应该注意哪些这样一段代码,qu对象是否需要垃圾回收?1for(inti=1;i2500;i++)2{3IQueryFilterqu=NewQueryFilterClass();//COM对象QueryFilterClass4qu.WhereClause=@Area=+i.ToString();5IFeatureCursorfeatCursor=featClass.Search(qu,true);//COM对象6//Usethefeaturecursorasrequired7System.Runtime.InteropServices.Marshal.ReleaseComObject(featCursor);8}1try{2ystem.Runtime.InteropServices.Marshal.ReleaseComObject(oField);3//感觉这里有些问题,它的oField在前面New了好多次,现在在最后清理,不知道是否真的起到了完全的作用?4System.Runtime.InteropServices.Marshal.ReleaseComObject(oFields);5System.Runtime.InteropServices.Marshal.ReleaseComObject(oFieldsEdit);6System.Runtime.InteropServices.

1 / 11
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功