
我正在Delphi XE2中构建一个多线程Windows服务应用程序,它使用ADO组件连接到SQL Server.我用过CoInitialize(零);程内部充足的时间,但在这种情况下,我有一个我不确定的功能.
此函数称为TryConnect,它尝试使用给定的连接字符串连接到.它在连接成功时返回true或false.问题是这个函数将在主服务线程的内部和外部使用,并且它将创建自己的临时TADOConnection组件,这需要CoInitialize …

先说说用getmodulehandle函数获取.此方法需要用createremotethread函数在远程进程中创建线程,让该线程调用kernel32.dll中的getmodulehandle函数.但是只这样还不行.因为getmodulehandle函数需要以dll模块文件名做参数.既然是远程线程调用getmodulehandle函数.还需要先把dll模块文件名写入目标进程的地址空间中.最后用createremotethread函数创建线程执行getmodulehandle函数来获取dll句柄。当按下选中键时,先判断是否已经选中了要移动的区域,如果已经选中了要移动的区域就调用move()函数完成由要移动的区域到要移动到的区域的移动过程,接着调用repaint()函数刷新屏幕,然后将已选择标记置成false,继续调用win()函数判断是否完成了任务,否则如果还没有选定要移动的区域则再判断当前选中区域是否为空白,如果不是空白就将选中标记置成true,然后刷新屏幕.这里介绍一个技巧,在开发程序遇到复杂的逻辑的时候,可以构造一格打印函数来将所关心的数据结构打印出来以利调试,这里我们就构造一个printgrid()函数,这个函数纯粹是为了调试之用,效果这得不错.至此我们完成了编码前的全部工作。由于是用createremotethread函数远程执行getmodulehandle函数.所以无法直接从getmodulehandle函数得到返回值(也就是dll句柄).在此必在waitforsingleobject函数之后用getexitcodethread函数来获取线程的退出代码.如果线程正确返回.该退出代码就是线程函数(getmodulehandle)的返回值然后再用同样的方法用createremotethread远程创建线程调用freelibrary函数来卸载该dll。
这是下面的代码……

//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;
所以为了澄清它真正在做什么,我可能有这样的机会:
CoInitialize(nil);
try
CoInitialize(nil);
try
//Do some ADO work
finally
CoUninitialize;
end;
finally
CoUninitialize;
end;
必须在使用COM的每个线程中调用CoInitialize,无论它是什么线程,或者它是否具有父线程或子线程.如果线程使用COM,则必须调用CoInitialize.
这里的正确答案是“它取决于”.由于您知道服务线程已调用CoInitialize,因此如果从服务线程调用TryConnect,则无需再次调用它.如果其他可以调用它的线程也调用CoInitialize,则不需要调用它,因为该函数将在调用线程下运行.
文档专门解决了这个问题(强调增加):
Typically, the COM library is initialized on a thread only once. Subsequent calls to CoInitialize or CoInitializeEx on the same thread will succeed, as long as they do not attempt to change the concurrency model, but will return S_FALSE. To close the COM library gracefully, each successful call to CoInitialize or CoInitializeEx, including those that return S_FALSE, must be balanced by a corresponding call to CoUninitialize. However, the first thread in the application that calls CoInitialize with 0 (or CoInitializeEx with COINIT_APARTMENTTHREADED) must be the last thread to call CoUninitialize. Otherwise, subsequent calls to CoInitialize on the STA will fail and the application will not work.
l不手工调用lock()和unlock()函数,一切交给栈上的guard对象的构造和析构函数负责,guard对象的生命期正好等于临界区(分析对象在什么时候析构是c+。不手工调用 lock() 和 unlock() 函数,一切交给栈上的 guard 对象的构造和析构函数负责,guard 对象的生命期正好等于临界区(分析对象在什么时候析构是 c+。在对象生命周期调用结束时coinitialize 多线程,__del__ 方法会被调用coinitialize 多线程,可以将__del__理解为“构析函数”。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-104630-1.html
苹果手机更新系统后又有好玩的了
喜欢哈哈