在线程里调用DCOMConnection.AppServer,提示“尚未调用CoInitialize”,怎么办?解决问题者,向阳渔港或石浦大酒店共进晚餐 (10

  • 主题发起人 主题发起人 李宝库
  • 开始时间 开始时间

李宝库

Unregistered / Unconfirmed
GUEST, unregistred user!
在线程里调用DCOMConnection.AppServer,提示“尚未调用CoInitialize”,怎么办?解决问题者,向阳渔港或石浦大酒店共进晚餐 (100分)<br />请大侠指教一二而已而已
 
在各个线程里都要单独调用CoInitialize和CoUnInitialize这个三明治代码。
http://www.delphibbs.com/delphibbs/dispq.asp?lid=2280814
 
是否在报务中。
 
什么意思?
部分代码,出错,怎么改:
procedure TSQLServerThread.Execute;
var
i:integer;
sSQLCommand:widestring;
vData:OleVariant;
tempstr:string;
begin
CoInitialize(nil);
try
sSQLCommand:='';
if Form1.dxBarCombo1.Text='成品' then
sSQLCommand:=sSQLCommand+
'select * from 产品库存 where 所在仓库='+''''+form1.Treeview1.Selected.Text+''''
else
sSQLCommand:=sSQLCommand+
'select * from 零配件库存 where 所在仓库='+''''+form1.Treeview1.Selected.Text+'''';
AppServer.QueryData(sSQLCommand,vData,tempstr);
FORM1.rsTemp.Close;
FORM1.rsTemp.XMLData:=vData;
FORM1.rsTemp.open;
finally
CoUninitialize;
end;
end;
 
应该在
CoInitialize
后面自己创建数据控件
而不要调用外面的
 
更正:AppServer.QueryData(sSQLCommand,vData,tempstr);
在我的程序里是:Form1.DCOMConnection1.AppServer.QueryData(sSQLCommand,vData,tempstr);
现在提示“应用程序调用一个已为另一线程整理的界面”
怎么办?
 
你自己创建一个dcom不就行了
 
TO:ycxy
你抬杠了,每个线程都创建一个DCOM连接那连接也太多了,显然不行
 
to 李宝库
你的线程要注意互斥
 
使用临界区互斥。看看TCriticalSection
线程中要支持DCOM必须调用coInitialize和couninitialize
 
nanami,能具体一点吗?请指教,最好给个范例程序
 
俺就是冲着那顿饭来的.,
线程中要FreeOnTerminate:=true;
数据库部件使用dbExpress
 
我要到龙泉山庄共进晚餐。
 
TO wwshuo,去那不是为难俺吗?把问题解决了怎么都好说
 
在你的线程中最下方,这样
initialization
Coinitialize(nil);
finalization
CoUninitialize;
行不行??
 
问题没解决!!
 
这篇文章对你不知道有没有用
Delphi COM编程的一个BUG
由于工作需要,得在一个DELPHI写的普通DLL中来调用一个VC写的进程内COM组件来实现功能。DLL很顺利就编写成功,但是在使用一个EXE程序来调试这个DLL时,DLL即总是报异常错误。,由于DLL所调用的这个使用VC写的这个COM组件在EXE中调用调试完全通过,所以其出错的可能性极小。我又非常的仔细检查了个用DELPHI写的DLL,也没有发现错误,却发现这个异常使用try和except还是可以拦住的,也就是说肯定是DELPHI本向所产生的异常。这就奇怪了,难道是DELPHI本身的问题造成的这种情况,我不敢肯定,所以只得从VCL源码一级来对这个程序进行除错。
在DLL中是COM对象是通过调用DELPHI的RTL函数CreateComObject来建立的,于是我先从这个函数入手开始调试。这个RTL函数很简单,只有一行代码:
OleCheck(CoCreateInstance(ClassID, nil, CLSCTX_INPROC_SERVER or
CLSCTX_LOCAL_SERVER, IUnknown, Result));

即使用Windows API函数CoCreateInstance函数来建立并返回COM组件的实例。这个API函数外面套了一层OleCheck函数,Delphi RTL函数OleCheck的作用是如果CoCreateInstance没有返回S_OK即COM组件建立成功,那么OleCheck将产生一个异常。我程序当中的异常会不会是这OleCheck函数调用所报出来的呢,于是我试着将OleCheck去掉,让把CoCreateInstance函数把其返回值显示出来。我试着运行修改过后的程序,呵呵CoCreateInstnace函数所返回的值果然不对,是2147746288十六进制数是800401F0。在MSDN中查得此值表示的含意是CoInitialize函数没有被调用。CoInitialize是COM组件的初始化函数,是DELPHI封装COM时绝对应该负责调用的东西,难道这次的错误真是由于没有调用CoInitialize函数所造成的,我半信半疑。试着将CoInitialize函数的调用加到了DLL单元的initialization部分,将CoUninitialize函数加到了DLL单元的finalization部分。再次使用外部EXE来调试这个DLL,果然不出错了。
错误是找到了,但是错误是怎样造成的呢。经过进一步的查找。发现错误出在Delphi的ComObj单元initialization部分。此处有以下一段代码:
if not IsLibrary then

begin

SaveInitProc := InitProc;

InitProc := @InitComObj;

end;

这段代码判断当前程序是否是一个DLL(通过IsLibrary变量来判断)如果不是的话,则将初始化的过程设为InitComObj函数。而DELPHI执行调用CoInitialize函数的操作正是在这个InitComObj函数中调用的,难快会出错。最终究其原因可能是宝兰的开发人员只注意到了ActiveX Library这类进程内COM框架的组件出始化的情况,而忘记了还可能有在普通DLL中调用COM组件来实现功能的情况造成了上述的错误。至此问题全部解决,不过笔者还想多说两句,就笔者认为对COM的支持是DELPHI做得比较差的地方之一,像这类错误在VC当中就根本不会出现的,真的是很希望宝兰的开发人员能在DELPHI6中把DELPHI对COM的支持做得更好,使DELPHI变得更加的完美。

 
implementation
uses Watherunt,Mainunt;
{ TWatchThread }
constructor TWatchThread.Create(MRenW:string;Path: string;
FNotifyFilter: Dword;
Dir: boolean;Topath:string);
begin
RenW:=MRenw;
MonitorPath:=path;
FNotify:=FNotifyFilter;
MonitorDir:=Dir;
ToServerPath:=Topath;
FreeOnTerminate :=true;
inherited Create(true);
end;


procedure TWatchThread.Execute;
begin

Mainfrm.Monitor2.RemoteMachineName:=PServerIp;//Monitor2是注册组件 只再这里用
while not Terminateddo
begin
//EnterCriticalSection(CS);//进入临界区
Watch(RenW,MonitorPath,FNotify,MonitorDir,ToServerPath);
//调用监视函数
//LeaveCriticalSection(CS);//退出临界区
end;
end;

initialization
Coinitialize(nil);
finalization
CoUninitialize;
end.

创建一个线程的时候提示 ‘尚没有Coinitialize‘
怎么办?
错误!
 

procedure TWatchThread.Execute;
begin
Coinitialize(nil);
Mainfrm.Monitor2.RemoteMachineName:=PServerIp;//Monitor2是注册组件 只再这里用
while not Terminateddo
begin
//EnterCriticalSection(CS);//进入临界区
Watch(RenW,MonitorPath,FNotify,MonitorDir,ToServerPath);
//调用监视函数
//LeaveCriticalSection(CS);//退出临界区
end;
CoUninitialize;
end;

end.
这种写法:
创建第两个线程提示
现在提示“应用程序调用一个已为另一线程整理的界面”
怎么办?
错误!
 
Mainfrm.Monitor2.RemoteMachineName:=PServerIp;//Monitor2是注册 tlb 组件 只再这里用
 
后退
顶部