线程里创建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是什么意思,
怎么用,什么时候用。
...全文
229 4 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
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

5,927

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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