如下是DELPHI7中的代码,运行完美通过。unit Unit1;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, OleServer, PCDLRN_TLB, StdCtrls, ActiveX, ComCtrls, ComObj;type
  tloadpc=class(tthread)
        protected
                procedure execute;override;
  end;    
  TForm1 = class(TForm)
    btn1: TButton;
    procedure btn1Click(Sender: TObject);  
  private
    { Private declarations }
  public
    { Public declarations }
  end;var
  Form1: TForm1;
  FAPP:IApplication;implementation
{$R *.dfm}  
procedure tloadpc.execute;
begin
  inherited;
        FAPP:=CreateOleObject('PCDLRN.Application') as IApplication;  
end;procedure TForm1.btn1Click(Sender: TObject);
begin
     tloadpc.Create(false); 
end;initialization
        CoInitializeEx(nil,0);
finalization
        CoUnInitialize;
end.但是在DELPHI2009是运行却是通不过的,因为DELPHI2009中竟然无法在单元初始化处为线程申请套间,郁闷……,所有代码改为如下:var
  Form1: TForm1;
  FAPP:IApplication;implementation
{$R *.dfm}  
procedure tloadpc.execute;
begin
  inherited;
        CoInitializeEx(nil,0);
        FAPP:=CreateOleObject('PCDLRN.Application') as IApplication;  
        CoUnInitialize;
end;procedure TForm1.btn1Click(Sender: TObject);
begin
     tloadpc.Create(false); 
end;但此时问题就出现了,在D7中线程结束后PCDLRN.EXE进程是不消失的,但是在DELPHI2009中随着线程EXECUTE过程的完毕PCDLRN.EXE进程也消失了,也就意味着后续无法再对该COM进行操作了,DELPHI2009做了个什么呀……,请大家帮忙,谢谢!

解决方案 »

  1.   

    在create里加一个 FreeOnTerminate := false; 试试,不知道2009是不是默认为true。 
    意思是线程结束后即释放。
      

  2.   

    CoInitializeEx在同一个进程当中是允许多次调用的,每调用一次就会增加一个计数,每调用CoUnInitialize又会释放一个计数,当计数为0时,所有相关的OLE/COM对象都会被释放。通过单元的initialization /finalization 调用初始化套间,那么就会依存于整个应用程序的生命周期当中,而如果是放到线程的Execute当中,那么当你调用了CoUnInitialize,如果此时套间被反初始化,那么所有建议的对象都会被释放,即使COM对象的引用计数不为零,生命周期未完成,但是由于COM套间被反初始化,仍然无法使用。
      

  3.   

    如果希望在线程当中初始化的对象能够在主线程当中使用,那么就应该先在主线程当中初始化COM套间。
      

  4.   

    十分感谢僵哥,但是如上我所述,DELPHI7是可以通过单元的initialization /finalization 调用初始化套间,但是在DELPHI2009中这样是不行的,有什么好的办法吗?
      

  5.   

    Delphi2009应该不会不行,应该只对主线程有效,对于COM套间的初始化,各线程需要各自维护,这也是一个好的作法,否则很容易造成内存泄露。
      

  6.   

    十分感谢僵哥,在DELPHI7中是可以通过单元的initialization /finalization 调用初始化套间的,但是在DELPHI2009中却是不可以的,有什么好的办法吗?
      

  7.   

    十分感谢僵哥, DELPHI2009真的是不可以的,如果是用DELPHI7的话那也就不会有这样的问题了,你可以自己用DELPHI2009和DELPHI7试一下,随便在线程中创建一个COM,如CREARTEOLEOBJECT('WORD.APPLICATION'),比较一下就知道了。
      

  8.   

    调用CoInitializeEx/CoInitialize的时候有没有检查过返回值?调用成功了吗?
      

  9.   


    ...
    procedure TMyComThread.Execute;
    begin
      CoInitializeEx(Nil, COINIT_MULTITHREADED);
      Excel := CreateOleObject('Excel.Application');
      CoUninitialize;
    end;
    ...
    initialization
      if CoInitializeEx(Nil, COINIT_MULTITHREADED) = RPC_E_CHANGED_MODE then begin
        CoUninitialize;
        CoInitializeEx(Nil, COINIT_MULTITHREADED);
      end;finalization
      CoUninitialize;
    end.
      

  10.   

    constructor TApplication.Create(AOwner: TComponent);
    var
    {$IF DEFINED(CLR)}
      SB: System.Text.StringBuilder;
      P: Integer;
      C: Char;
    {$ELSE}
      P: PChar;
      ModuleName: array[0..255] of Char;
    {$IFEND}
    begin
      inherited Create(AOwner);
      if not IsLibrary then
        FNeedToUninitialize := Succeeded(OleInitialize(nil));//问题应该是出在这里
      if not Assigned(Classes.ApplicationHandleException) then
      

  11.   


    DELPHI2009环境下,在单元的INITIALIZATION处调用COINITIALIZEEX返回是失败的
      

  12.   

    感谢大家,问题已经解决。
    CODE GEAR程序员考虑的太多而且太仔细,所以导致了多线程操作COM时无法在主线程内为其申请线程套间,问题就是出现在僵哥所提的那一点上问题原因解释:OleInitialize在内部调用CoInitializeEx来初始化COM库。因为OLE操作不是线程安全的,所以OleInitialize指定运行模式为single-thread apartment修改办法:
    将OleInitialize改为CoInitializeEx(nil,0)在DESTROY实现部分将OleUnInitialize改为CoUnInitialize问题进一步分析:其实CODE GEAR的初衷是其常好的,他们也想模仿微软的C#,实现多线程操作COM时的程序员不参与性,可惜用错了东西,如果您要自行进行申请套间,还有另一种修改方案,那就是将这些所谓为程序省事的部分(CREATE和DESTROY实现内的OleInitialize操作部分)删掉。另外多插一句,CODE GEAR官方网站最新的DELPHI版本安装后在安装目录的SOURCE文件内只有一个dUnit文件夹,其它的都没有了(像database,Win32...),不知道CODE GEAR做这些一初是怎么想的。再次感谢大家对该问题的关心。