不调CoUninitialize会否有问题?

imisewer 2008-06-23 03:52:30
在dll中动态创建XmlDoc并操作的接口函数中首尾对应写了ActiveX.Coinitialize与CoUninitialize,结果运行到DLL中的CoUninitialize有无法捕获的异常,如果dll中不加这两句代码而加在Exe中则没有问题.

有朋友告诉我说把后面的CoUninitialize代码注释掉.
若在DLL中不调用CoUninitialize会有什么问题?

delphi的帮助文档中说
Comments
Typically, CoInitialize is called only once in the process that uses the OLE library. There can be multiple calls, but subsequent calls return S_FALSE. To close the library gracefully, each successful call to CoInitialize, including those that return S_FALSE, must be balanced by a corresponding call to the CoUninitialize function.
最后一句说每个CoInitialize的调用都要有CoUninitialize来一一对应.

请高手指点....THX
...全文
2347 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
Simmy_Nie 2009-01-14
  • 打赏
  • 举报
回复
首先要搞清楚CoInitialize是做什么用的。初始化COM库的。

如果只是在主线程中用到COM组件,当然工作线程就没必要进行CoInitialize。

如果两个线程中要用同一个COM组件,并都是STA的话,那么就是跨套间了。
比如在主线程中获得了COM对象的接口,并要把接口传入到工作线程中使用,那么需要对接口进行列集散集
用到API为 CoMarshalInterThreadInterfaceInStream 和 CoGetInterfaceAndReleaseStream

对于没有调用CoUninitialize,后面如要再调用CoInitialize时就会失败了。
程序不出错不代表没有问题。应当成对调用。
Behard 2008-12-23
  • 打赏
  • 举报
回复
还是建议写到 entry 中,好像 xxx.free 会调用需要系统自动释放的东西
要把你在 CoUninitialize 之前加 sleep() 和 peekmessage 试一试
transicz 2008-12-19
  • 打赏
  • 举报
回复
在调用主程序中添加下面代码试试:
initialization
CoInitializeEx(nil,COINIT_MULTITHREADED);
finalization
CoUninitialize;
imisewer 2008-06-24
  • 打赏
  • 举报
回复
还有没有人知道是怎么回事呢??
liangpei2008 2008-06-23
  • 打赏
  • 举报
回复
学习
imisewer 2008-06-23
  • 打赏
  • 举报
回复
加一句AXml:=Nil;无效
把AXml.Free改为FreeAndNil(AXml)也无效
执行到CoUninitialize会报Access Violation
若将最后的try except取消注释 此处无法捕获取异常信息
僵哥 2008-06-23
  • 打赏
  • 举报
回复
不知道异常信息是什么样的?

AXml.Free;
后面增加一条
AXml := Nil;
看看是否有效。
imisewer 2008-06-23
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 unsigned 的回复:]
不清楚你具体如何写法。其实个人比较建议的办法是,在线程需要操作COM的线程当中去初始化,即线程的Execute当中。之所以在DLL当中处理,为的是防止别人在使用的时候存在不方便。
[/Quote]
EXE的窗体中就一个BUTTON及ONCLICK

procedure TForm1.Button1Click(Sender: TObject);
var
ret:WideString;
begin
ret:=GetXmlStr; //声明于DLL中的接口
ShowMessage(ret);
end;

Dll中接口代码

function GetXmlStr:WideString;stdcall;
var
AComp:TComponent;
AXml:TXmlDocument;
begin
Activex.CoInitialize(nil);
try
AComp:=TComponent.Create(nil);
AXml:=TXmlDocument.Create(AComp);
try
AXml.Active:=True;
AXml.DocumentElement:=AXml.CreateNode('TestRoot');
AXml.DocumentElement.Attributes['DateTime']:=FormatDateTime('YYYYMMDDHHMMSSZZZ',Now);
Result:=AXml.XML.Text;
finally
AXml.Free;
AComp.Free;
end;
except on e:Exception do
Result:=e.Message;
end;
// try
activex.CoUninitialize;
// except on e:Exception do
// Result:=Result+'===='+e.Message;
// end;
end;


已经是很简单的了 所以一直想不明白.
僵哥 2008-06-23
  • 打赏
  • 举报
回复
不清楚你具体如何写法。其实个人比较建议的办法是,在线程需要操作COM的线程当中去初始化,即线程的Execute当中。之所以在DLL当中处理,为的是防止别人在使用的时候存在不方便。
imisewer 2008-06-23
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 unsigned 的回复:]
在COM当中大部分用到的是接口,当你的接口还没有释放之前就执行CoUninitialize,那么这些接口就会被释放掉,但是由于这些接口编译器所编译的代码当中就存在释放代码,所以又会去执行这部分代码,如此就异常了。
[/Quote]

首先感谢您的回复.但还有不明:
我在function AAA:WideString;stdcall;中动态创建了Component和XmlDocument对象(局部变量),并均在函数体内调free释放,且代码全包含在CoInitialize与CoUninitialize之间,不明白为什么这样也会有问题,而且还是无法捕获的异常.
僵哥 2008-06-23
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 imisewer 的回复:]
引用 1 楼 unsigned 的回复:
不仅仅只是一一对应,并且要求是在同一线程当中。

对于DLL,最好放到DllEntry当中

Delphi(Pascal) codeprocedure DllEntry(Reason: Integer);
begin
case Reason of
DLL_PROCESS_ATTACH,
DLL_THREAD_ATTACH:CoInitialize;

DLL_PROCESS_DETACH,
DLL_THREAD_DETACH:CoUninitialize;
end;
end;


用这样的方法CoUninitialize是不会异常,但为什么写…
[/Quote]
在COM当中大部分用到的是接口,当你的接口还没有释放之前就执行CoUninitialize,那么这些接口就会被释放掉,但是由于这些接口编译器所编译的代码当中就存在释放代码,所以又会去执行这部分代码,如此就异常了。
imisewer 2008-06-23
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 unsigned 的回复:]
不仅仅只是一一对应,并且要求是在同一线程当中。

对于DLL,最好放到DllEntry当中

Delphi(Pascal) codeprocedure DllEntry(Reason: Integer);
begin
case Reason of
DLL_PROCESS_ATTACH,
DLL_THREAD_ATTACH:CoInitialize;

DLL_PROCESS_DETACH,
DLL_THREAD_DETACH:CoUninitialize;
end;
end;
[/Quote]

用这样的方法CoUninitialize是不会异常,但为什么写成如下就会有无法捕获的异常了呢?
function AAA:WideString;stdcall;
begin
CoInitializa(nil);
......
......
CoUninitialize; //执行至此则异常
end;
DumDum 2008-06-23
  • 打赏
  • 举报
回复
好像有问题,但是有什么不明~~~!
僵哥 2008-06-23
  • 打赏
  • 举报
回复
不仅仅只是一一对应,并且要求是在同一线程当中。

对于DLL,最好放到DllEntry当中
procedure DllEntry(Reason: Integer);
begin
case Reason of
DLL_PROCESS_ATTACH,
DLL_THREAD_ATTACH:CoInitialize;

DLL_PROCESS_DETACH,
DLL_THREAD_DETACH:CoUninitialize;
end;
end;

1,183

社区成员

发帖
与我相关
我的任务
社区描述
Delphi Windows SDK/API
社区管理员
  • Windows SDK/API社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧