您的位置:首页 > 其它

ae的com对象在dotnet中的释放问题

2016-05-02 19:06 330 查看
转自:AE的COM对象在.NET中的释放问题


ae的com对象在dotnet中的释放问题

ae的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引用计数
IWorkspaceFactory wsf = new AccessWorkspaceFactoryClass();
IWorkspace ws = wsf.OpenFromFile(mdbPath, 0);
IFeatureClass fls = ((IFeatureWorkspace)ws).OpenFeatureClass(featureClassName);
IWorkspace ws1 = ws;
int i = Marshal.ReleaseComObject(ws);


i的值为0。
情况二:新声明一个workspace局部变量,通过IDataset.Workspace属性给新变量赋值,释放workspace,查看workspace引用计数
IWorkspaceFactory wsf = new AccessWorkspaceFactoryClass();
IWorkspace ws = wsf.OpenFromFile(mdbPath, 0);
IFeatureClass fls = ((IFeatureWorkspace)ws).OpenFeatureClass(featureClassName);
IWorkspace ws1 = ((IDataset)fls).Workspace;
int i = Marshal.ReleaseComObject(ws);


i的值为1。
我大胆的得出结论(有可能不对):将COM接口指针映射到运行时可调用包装操作是在调用执行com对象方法并返回值时才会发生。
情况三:在一个方法里面打开featureclass,不释放workspace,新声明一个workspace局部变量,通过IDataset.Workspace属性给新变量负责,释放workspace,查看workspace引用计数
private IFeatureClass getFclss(string path, string featureClassName)
{
IWorkspaceFactory wsf = new AccessWorkspaceFactoryClass();
IWorkspace ws = wsf.OpenFromFile(path, 0);
return ((IFeatureWorkspace)ws).OpenFeatureClass(featureClassName);
}
IFeatureClass fls = getFclss(mdbPath, featureClassName);
IWorkspace ws = ((IDataset)fls).Workspace;
int i = Marshal.ReleaseComObject(ws);


i的值为1。
情况四:跟情况三类似,不同的是调用了GC.Collect方法

IFeatureClass fls = getFclss(mdbPath, featureClassName);

GC.Collect();

IWorkspace ws = ((IDataset)fls).Workspace;

int i = Marshal.ReleaseComObject(ws);


i的值为0。
比较情况三跟情况四,可以得出结论,释放COM对象在dotnet中的映射对象的时候,引用计数会减一
情况五:调用情况三的获取featureclass的方法,释放得到的featureclass,删除mdb文件

IFeatureClass fls = getFclss(mdbPath, featureClassName);

Marshal.ReleaseComObject(fls);

File.Delete(mdbPath);


得到“文件“。。。”正由另一进程使用,因此该进程无法访问该文件。”的异常。
情况六:修改getFclss方法,在方法内释放掉worksapce,再像情况五一样操作

private IFeatureClass getFclss(string path, string featureClassName)

{

IWorkspaceFactory wsf = new AccessWorkspaceFactoryClass();

IWorkspace ws = wsf.OpenFromFile(path, 0);

try

    {

return ((IFeatureWorkspace)ws).OpenFeatureClass(featureClassName);

}

finally

    {

Marshal.ReleaseComObject(ws);

}

}


这时可以删除掉文件。
情况七:调用情况六修改后的getFclss,不释放featureclass,直接删除文件

IFeatureClass fls = getFclss(mdbPath, featureClassName);

File.Delete(mdbPath);


得到情况五一样的异常。
情况八:调用情况六修改后的getFclss,新声明一个workspace局部变量,通过IDataset.Workspace属性给新变量赋值。

IFeatureClass fls = getFclss(mdbPath, featureClassName);

IWorkspace ws = ((IDataset)fls).Workspace;


这时得到的ws是可以查看属性的,释放后的com对象查看属性会得到提示为“COM 对象与其基础 RCW 分开后就不能再使用。”的异常。
情况九:workspace打开ifeatureclass2次

IWorkspaceFactory wsf = new AccessWorkspaceFactoryClass();

IWorkspace ws = wsf.OpenFromFile(mdbPath, 0);

IFeatureClass fcls= ((IFeatureWorkspace)ws).OpenFeatureClass(featureClassName);

IFeatureClass fcls1 = ((IFeatureWorkspace)ws).OpenFeatureClass(featureClassName);

int i = Marshal.ReleaseComObject(fcls);


i的值为1。
那么对于访问COM对象属性的属性的情况会是怎么样呢。
情况十:创建getDataset方法,跟新的getFclss一样,只是返回的是IDataset,访问IDataset.Workspace,再访问IDataset.Workspace.PathName,释放workspace,查看引用计数

private IDataset getDataset(string path, string featureClassName)

{

IWorkspaceFactory wsf = new AccessWorkspaceFactoryClass();

IWorkspace ws = wsf.OpenFromFile(path, 0);

try

    {

return ((IFeatureWorkspace)ws).OpenFeatureClass(featureClassName) as IDataset;

}

finally

    {

Marshal.ReleaseComObject(ws);

}

}

IDataset ds = getDataset(mdbPath, featureClassName);

IWorkspace ws = ds.Workspace;

string s = ds.Workspace.PathName;

     int i = Marshal.ReleaseComObject(ws);


i的值为1。
所以,为了避免有的对象释放漏掉,最好不要使用IDataset.Workspace.PathName这种写法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: