什么时候需要调用CoInitialize

什么时候需要调用CoInitialize

本文介绍了在这种情况下,什么时候需要调用CoInitialize()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在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 ,无论它是什么线程,还是有父线程或子线程。如果线程使用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()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 15:46