问题描述
我正在Delphi XE2中构建一个多线程Windows服务应用程序,它使用ADO数据库组件连接到SQL Server。我在线程内部使用了 CoInitialize(nil);
很多次,但在这种情况下,我有一个我不确定的功能。 此函数称为 TryConnect
,它尝试使用给定的连接字符串连接到数据库。它在连接成功时返回true或false。问题是这个函数将在主服务线程内部和外部使用,它将创建自己的临时 TADOConnection
组件,这需要 CoInitialize
...
我的问题是我需要在此内调用 CoInitialize
功能也是如果我这样做,并且由于服务的执行过程也使用 CoInitialize
,如果我从服务中调用此函数,它们是否会干扰? TryConnect
函数在从主服务线程创建的对象的内部(但最终将被移动到自己的线程)。我需要知道如果从同一个线程(和 CoUninitialize
)调用 CoInitialize()
将会干扰 - 以及如何
这是下面的代码...
//这是服务应用程序的执行过程
procedure TJDRMSvr.ServiceExecute(Sender:TService);
begin
try
CoInitialize(nil);
启动;
尝试
而不终止do begin
DoSomeWork;
ServiceThread.ProcessRequests(False);
结束
finally
清理;
CoUninitialize;
结束
除了
在e:exception do begin
PostLog('EXCEPTION in Execute:'+ e.Message);
结束
结束
结束
// TryConnect可以从同一个服务线程调用另一个线程
函数TDBPool.TryConnect(const AConnStr:String):Bool;
var
DB:TADOConnection; //这个功能需要CoInitialize吗?
begin
结果:= False;
DB:= TADOConnection.Create(nil);
try
DB.LoginPrompt:= False;
DB.ConnectionString:= AConnStr;
try
DB.Connected:= True;
结果:= True;
除了
对e:exception do begin
end;
结束
DB.Connected:= False;
finally
DB.Free;
结束
结束
所以要澄清一下它真正在做什么,我可能有机会:
CoInitialize(nil);
try
CoInitialize(nil);
try
//做一些ADO工作
finally
CoUninitialize;
结束
finally
CoUninitialize;
结束
CoInitialize $ c必须在使用COM的每个线程中调用$ c>,无论它是什么线程,还是有父线程或子线程。如果线程使用COM,它必须调用
CoInitialize
。
正确的答案是这取决于。由于您知道服务线程已调用 CoInitialize
,如果从服务线程调用 TryConnect
,则不需要再次打电话如果可以调用它的其他线程也称为 CoInitialize
,则不需要调用,因为函数将在调用线程下运行。
文档专门解决了这个问题(增加了重点):
所以答案是:如果你不确定,调用 CoInitialize
。在 try..finally
块中执行此操作,并在中调用
CoUnitialize
code>,或者在构造函数中初始化,并在析构函数中初始化。
I'm building a multi-threaded windows service application in Delphi XE2 which uses ADO database components to connect to SQL Server. I've used CoInitialize(nil);
plenty times before inside threads, but in this case, I have a function which I'm unsure about.
This function is called TryConnect
which attempts to connect to a database with a given connection string. It returns true or false on the connection success. The problem is that this function will be used both inside and outside the main service thread, and it will be creating its own temporary TADOConnection
component, which requires CoInitialize
...
My question is do I need to call CoInitialize
inside this function also? If I do, and since the service's execute procedure uses CoInitialize
also, will they interfere if I call this function from within the service? The TryConnect
function is inside of an object which is created from the main service thread (but will eventually be moved to its own thread). I need to know if calling CoInitialize()
twice from the same thread (and CoUninitialize
) will interfere - and how to handle this scenario properly.
Here's the code below...
//This is the service app's execute procedure
procedure TJDRMSvr.ServiceExecute(Sender: TService);
begin
try
CoInitialize(nil);
Startup;
try
while not Terminated do begin
DoSomeWork;
ServiceThread.ProcessRequests(False);
end;
finally
Cleanup;
CoUninitialize;
end;
except
on e: exception do begin
PostLog('EXCEPTION in Execute: '+e.Message);
end;
end;
end;
//TryConnect might be called from same service thread and another thread
function TDBPool.TryConnect(const AConnStr: String): Bool;
var
DB: TADOConnection; //Do I need CoInitialize in this function?
begin
Result:= False;
DB:= TADOConnection.Create(nil);
try
DB.LoginPrompt:= False;
DB.ConnectionString:= AConnStr;
try
DB.Connected:= True;
Result:= True;
except
on e: exception do begin
end;
end;
DB.Connected:= False;
finally
DB.Free;
end;
end;
So to clarify what it's really doing, I might have an occasion of this:
CoInitialize(nil);
try
CoInitialize(nil);
try
//Do some ADO work
finally
CoUninitialize;
end;
finally
CoUninitialize;
end;
CoInitialize
has to be called in every single thread that uses COM, regardless of what thread it is, or whether it has a parent thread or child threads. If the thread uses COM, it must call CoInitialize
.
The correct answer here is "it depends". Since you know the service thread has called CoInitialize
, if TryConnect
is called from the service thread it won't need to be called again. If the other threads that could call it have also called CoInitialize
, it won't need to be called, as the function will run under the calling thread.
The MSDN documentation specifically addresses this question (emphasis added):
So the answer is: If you're not sure, call CoInitialize
. Do it in a try..finally
block, and call CoUnitialize
in the finally
, or initialize in a constructor and uninitialize in the destructor.
这篇关于在这种情况下,什么时候需要调用CoInitialize()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!