Einzelnen Beitrag anzeigen

crypti

Registriert seit: 12. Feb 2005
43 Beiträge
 
#1

COM-Server als Singleton umsetzen

  Alt 4. Jan 2009, 10:37
Hallo Leute!

Ich hoffe auch ihr seit gut ins Jahr 2009 gerutscht.

Ich versuche mich hier gerade an der Umsetzung einer ActiveX Bibliothek die über die von Delphi bekannten Automatisierungsobjekte enthält. Soweit alles ok, funktioniert auch super. Da ich jedoch in der Bibliothek eine Datenbank verwenden will, muss der Einstieg den die Anwendungen über COM nutzen ein Singleton sein. Also alle bekommen die gleiche Instanz der Anwendung zugeteilt.

Delphi-Quellcode:
unit COM_MyServer;

{$WARN SYMBOL_PLATFORM OFF}

interface

uses
  ComObj, ActiveX, MyServerLib_TLB, StdVcl, Windows;

type
  TSingletonAutoObjectFactory = class(TAutoObjectFactory)
  private
    FCOMObj : TComObject;
  protected
    { Protected-Deklarationen }
    function CreateComObject(const Controller: IUnknown): TComObject; override;
    destructor Destroy; override;
  end;

type
  TMyServer = class(TAutoObject, IMyServer)
  private
    bIsLoaded : Boolean;
  protected
    procedure TestServer; safecall;
    function InitDB: Integer; safecall;
  end;

implementation

uses ComServ;

{ TMyServer }

procedure TMyServer.TestServer;
begin
     windows.OutputDebugString(PCHAR('TMyServer.TestServer: erfolgreich ausgeführt'));
end;

function TMyServer.InitDB: Integer;
begin
     if (bIsLoaded = true) then
     begin
          windows.OutputDebugString(PCHAR('TMyServer.InitDB: DB allready loaded'));
     end
     else
     begin
          bIsLoaded:=true;
     end;
end;


{ TSingeltonAutoObjectFactory }

function TSingletonAutoObjectFactory.CreateComObject(const Controller: IInterface): TComObject;
begin
     if FCOMObj = nil then
          FCOMObj := inherited CreateComObject(Controller);

     result := FCOMObj;
end;

destructor TSingletonAutoObjectFactory.Destroy;
begin
     FCOMObj := nil;
     inherited;
end;


initialization
// TAutoObjectFactory.Create(ComServer, TMyServer, Class_MyServer,
// ciMultiInstance, tmApartment);
  TSingletonAutoObjectFactory.Create(ComServer, TMyServer, Class_MyServer,
    ciMultiInstance, tmApartment);

end.
Der zugehörige Client sieht ganz einfach aus. Dieser importiert die TLB und greift dann auf den Server zu.

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
    MyServer:=CoMyServer.Create;

    MyServer.TestServer();

    MyServer.InitDB();
end;
Nun ist mein Problem, dass diese Singleton-Umsetzung nicht ganz funktioniert. Wenn ich in in EINER Anwendung den ButtonClick mehrfach ausführe, dann erhalte ich im COM-Server auch die Meldung, dass die DB bereits initialisiert wurde. Klappt also wunerbar, ist ein Singleton.
Wenn ich jedoch diese Clientanwendung parallel ein zweites (drittes...) Mal starte und die Aktion ausführe, dann verhalten sich diese genauso wie die erste. Beim ersten Klick wird die DB initialisiert und dann nicht mehr.

Was ich nun gern hätte ist ein übergreifendes Singleton. Egal wie viele Programme darauf zugreifen, alle bekommen die gleiche Instanz. Momentan scheint das Singleton nur an die aufrufende Programminstanz gebunden zu sein.

Hat jemand da eine (oder mehrere) Ideen? Schon mal Danke im Voraus!
  Mit Zitat antworten Zitat