• 主页
  • 招聘
  • 语言基础/算法/系统设计
  • 数据库相关
  • 图形处理/多媒体
  • 网络通信/分布式开发
  • VCL组件开发及应用
  • Windows SDK/API

线程里创建com对象,提示没调用CoInitialize

Drunkard2000 2004-12-22 12:33:15
constructor TListRecorder.Create;
begin
CoInitialize(nil); //后来去掉了,也没关系的样子
CDBWork1 := TCDBWork.Create(nil); //com对象

query := TAdoQuery.Create(nil); //com对象
inherited Create(True);
end;

procedure TListRecorder.Execute;
var
s: _Stream;
buf: Variant;
rs: _Recordset;
Param: TQueryRecordParam;
begin
.....
....
CoInitialize(nil); //后来加的,加了就没问题了
CDBwork1.RemoteMachineName := frmMain.RecorderServerIP;
CDBwork1.Connect;
if CDBWork1.pConnected then
....
....
end;


本来只有在create 里才有CoInitialize,但还是报错,我就在Execute又加了一个;可以了
是不是创建时,我把create 里的去掉了,也没问题,我想问一下CoInitialize是什么意思,
怎么用,什么时候用。
...全文
188 点赞 收藏 4
写回复
4 条回复
zeroxing 2004年12月22日
CoInitialize这个东西,在每个线程里面都要调用一次而且仅调用一次,才可以调用com的东东。

楼主放在Create里面和放在Execute是截然不同的,前者是由创建这个线程的那个线程(往往是主线程)调用的,而后者才是真正在你的本线程跑的,就是说Create里面跑的东西不是你的子线程。可以看看这一贴:

http://community.csdn.net/Expert/topic/3650/3650597.xml?temp=.3319971
回复 点赞
Kevin_Lmx 2004年12月22日
CoInitialize用来初始化一个Com对象
回复 点赞
halfdream 2004年12月22日

COM定义了两种类型的套间,STA(单线程套间)和MTA(多线程套间)。

STA的特点是套间内永远只有一个线程运行,并且一定是创建该套间的初始线程。因而开发只运行在STA中的组件不需要考虑线程同步等问题。

MTA的特点是套间内可以有多个线程运行,并且还可以创建新的线程。在MTA中运行的组件必须自己实现线程的同步。

套间的进入和退出:
线程通过CoInitializeEx函数进入套间,该函数的第二个参数通过传递COINIT_APARTMENTTHREADED和COINIT_MULTITHREADED标志了套间类型。如果传递COINIT_APARTMENTTHREADED,该线程将创建自己私有的套间STA,别人不能进入。如果传递COINIT_MULTITHREADED,该线程将进入当前进程范围内的MTA。

线程调用CoUninitialize函数用于退出所在的套间。只有退出后才可以进入其它类型的套间。


------------------------------------------------------------------------------
楼主,DELPHI的APPLICATION缺省的主线程已经调用过CoInitialize,进入了一个STA,
而你的工作线程是进入MTA,我想这是你程序报错原因...


你在主线程创建COM对象时,可先退出STA,然后再进入MTA创建COM...这样在工作线程的MTA就可以访问到这个COM了.

强烈建议不这样做!不要随便用MTA...

1,COM组件本身的实现往往是STA的..客户与服务的线程模式匹配才能有较高效率.
2,MTA 把线程安全性的责任交给了你..要特别小心...



回复 点赞
Drunkard2000 2004年12月22日
明白了,谢谢。再问一个问题,
我用 CoInitializeEx(nil,COINIT_MULTITHREADED);在子线程初始化

//frmMain.主窗体,CDBWork1,主窗体中com对象
procedure TListRecorder.Execute;
var
s: _Stream;
buf: Variant;
rs: _Recordset;
Param: TQueryRecordParam;
begin
.....
....
CoInitializeEx(nil,COINIT_MULTITHREADED);//初试化
frmMain.CDBwork1.RemoteMachineName := frmMain.RecorderServerIP;
frmMain.CDBwork1.Connect;
if frmMain.CDBWork1.pConnected then
....
....
end;

使现成能调用主线程里的com对像,报错:
the application called an interface that
was marshalled for different thread
回复 点赞
发动态
发帖子
Delphi
创建于2007-08-02

1474

社区成员

26.2w+

社区内容

Delphi 开发及应用
社区公告
暂无公告