mthreaddcom.pas

来自「详细说明:毕业论文中关于小型宾馆管理系统的详细设计毕 业论文中关于小型宾馆...」· PAS 代码 · 共 171 行

PAS
171
字号
{*******************************************************}
{                                                       }
{          Threaded Class Factory Demo                  }
{                                                       }
{*******************************************************}

unit MThreadDCOM;

{
  This unit provides some custom class factories that implement threading for
  out of process servers.  The TThreadedAutoObjectFactory is for any TAutoObject
  and the TThreadedClassFactory is for and TComponentFactory.  To use them,
  replace the line in the initialization section of your automation object to
  use the appropriate threaded class factory instead of the non-threaded version.
}

interface

uses ComObj, ActiveX, Classes, Windows, VCLCom, Forms;

type

  TCreateInstanceProc = function(const UnkOuter: IUnknown;
    const IID: TGUID; out Obj): HResult of object; stdcall;

{ TThreadedAutoObjectFactory }

  TThreadedAutoObjectFactory = class(TAutoObjectFactory, IClassFactory)
  protected
    function CreateInstance(const UnkOuter: IUnknown; const IID: TGUID;
      out Obj): HResult; stdcall;
    function DoCreateInstance(const UnkOuter: IUnknown; const IID: TGUID;
      out Obj): HResult; stdcall;
  end;

{ TThreadedClassFactory }

  TThreadedClassFactory = class(TComponentFactory, IClassFactory)
  protected
    function CreateInstance(const UnkOuter: IUnknown; const IID: TGUID;
      out Obj): HResult; stdcall;
    function DoCreateInstance(const UnkOuter: IUnknown; const IID: TGUID;
      out Obj): HResult; stdcall;
  end;

{ TApartmentThread }

  TApartmentThread = class(TThread)
  private
    FCreateInstanceProc: TCreateInstanceProc;
    FUnkOuter: IUnknown;
    FIID: TGuid;
    FSemaphore: THandle;
    FStream: Pointer;
    FCreateResult: HResult;
  protected
    procedure Execute; override;
  public
    constructor Create(CreateInstanceProc: TCreateInstanceProc; UnkOuter: IUnknown; IID: TGuid);
    destructor Destroy; override;
    property Semaphore: THandle read FSemaphore;
    property CreateResult: HResult read FCreateResult;
    property ObjStream: Pointer read FStream;
  end;

implementation

{ TThreadedAutoObjectFactory }

function TThreadedAutoObjectFactory.DoCreateInstance(const UnkOuter: IUnknown;
  const IID: TGUID; out Obj): HResult; stdcall;
begin
  Result := inherited CreateInstance(UnkOuter, IID, Obj);
end;

// NOTE: Additions suggested by Binh Ly
// http://www.castle.net/~bly/Programming/Delphi/Threading2/index.html)
function TThreadedAutoObjectFactory.CreateInstance(const UnkOuter: IUnknown;
  const IID: TGUID; out Obj): HResult; stdcall;
begin
  LockServer(TRUE);
  try
    with TApartmentThread.Create(DoCreateInstance, UnkOuter, IID) do
    begin
      if WaitForSingleObject(Semaphore, INFINITE) = WAIT_OBJECT_0 then
      begin
        Result := CreateResult;
        if Result <> S_OK then Exit;
        Result := CoGetInterfaceAndReleaseStream(IStream(ObjStream), IID, Obj);
      end else
        Result := E_FAIL
    end;
  finally
    LockServer(FALSE);
  end;
end;

{ TThreadedClassFactory }

function TThreadedClassFactory.DoCreateInstance(const UnkOuter: IUnknown;
  const IID: TGUID; out Obj): HResult; stdcall;
begin
  Result := inherited CreateInstance(UnkOuter, IID, Obj);
end;

// NOTE: Additions suggested by Binh Ly
// http://www.castle.net/~bly/Programming/Delphi/Threading2/index.html)
function TThreadedClassFactory.CreateInstance(const UnkOuter: IUnknown;
  const IID: TGUID; out Obj): HResult; stdcall;
begin
  LockServer(TRUE);
  try
    with TApartmentThread.Create(DoCreateInstance, UnkOuter, IID) do
    begin
      if WaitForSingleObject(Semaphore, INFINITE) = WAIT_OBJECT_0 then
      begin
        Result := CreateResult;
        if Result <> S_OK then Exit;
        Result := CoGetInterfaceAndReleaseStream(IStream(ObjStream), IID, Obj);
      end else
        Result := E_FAIL
    end;
  finally
    LockServer(FALSE);
  end;
end;

{ TApartmentThread }

constructor TApartmentThread.Create(CreateInstanceProc: TCreateInstanceProc;
  UnkOuter: IUnknown; IID: TGuid);
begin
  FCreateInstanceProc := CreateInstanceProc;
  FUnkOuter := UnkOuter;
  FIID := IID;
  FSemaphore := CreateSemaphore(nil, 0, 1, nil);
  FreeOnTerminate := True;
  inherited Create(False);
end;

destructor TApartmentThread.Destroy;
begin
  FUnkOuter := nil;
  CloseHandle(FSemaphore);
  inherited Destroy;
  Application.ProcessMessages;
end;

procedure TApartmentThread.Execute;
var
  msg: TMsg;
  Unk: IUnknown;
begin
  CoInitialize(nil);
  FCreateResult := FCreateInstanceProc(FUnkOuter, FIID, Unk);
  if FCreateResult = S_OK then
    CoMarshalInterThreadInterfaceInStream(FIID, Unk, IStream(FStream));
  ReleaseSemaphore(FSemaphore, 1, nil);
  if FCreateResult = S_OK then
    while GetMessage(msg, 0, 0, 0) do
    begin
      DispatchMessage(msg);
      Unk._AddRef;
      if Unk._Release = 1 then break;
    end;
  Unk := nil;
  CoUninitialize;
end;

end.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?