Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi COM Objekte in Threads. Wie geht das richtig ? (https://www.delphipraxis.net/60239-com-objekte-threads-wie-geht-das-richtig.html)

jensw_2000 4. Jan 2006 13:28


COM Objekte in Threads. Wie geht das richtig ?
 
Liste der Anhänge anzeigen (Anzahl: 2)
Ich versuche grade ein älteres Projekt komplett auf CoKlassen umzustellen. Die CoClasses sollen zusätzlich noch in Threads verwendet werden. Datei habe mich von Alzaimars Thread-Job Beispiel insprieren lassen.

Zurzeit kämpfe ich damit, die COM-Objekte in den Threads direkt anzusprechen (anstatt importierte Klassen zu verwenden), jedoch erhalte beim Hinzufügen von Jobs zur Jobliste immer folgende Fehlermeldung :

Zitat:

Eine Schnittstelle, die für einen anderen Thread marshalled war, wurde von der Anwendung aufgerufen.
Ich habe beim Googeln jemanden gefunden der das gleiche Problem hatte, jedoch verstehe ich nicht, warum der Fehler bei mir auftritt.

In dem Newsgroup-Artikel kann ich das Problem nachvollziehen, weil im Hauptthread ein COM Objekt erzeugt wird, auf das mehrere Threads zugreifen.

Bei mir hat jeder "Workerthread" eine eigene Instanz des COM-Objektes. Somit sollte es doch keine Kollisionen geben oder ? :gruebel:


Das Thread-Objekt ...
Delphi-Quellcode:
  TWorkerThread = class(TThread)
  private
    fID: Integer;
    fCallObj: DIVASDKLIB_TLB.IDivaCall;
    fDivaCallEvents: TDIVASDKLibIDivaCallEvents;
    procedure DoExecuteJob(ajob: TJob);
    procedure DivaCallEventsConnected(Sender: TObject);
    procedure DivaCallEventsDisconnected(Sender: TObject);
    procedure DivaCallEventsToneReceived(Sender: TObject; cTone: Byte);
  protected
    constructor Create(aID: Integer);
    destructor Destroy;
    procedure Execute; override;
  end; //TWorkerThread
...

Delphi-Quellcode:
constructor TWorkerThread.Create(aID: Integer);
begin

  CoInitialize(nil);

  inherited Create(True);
  fID := aID;

  // Instanz von IDivaCall erzeugen und konfigurieren
  fCallObj := InstObj.CreateCall as DIVASDKLIB_TLB.IDivaCall;
  fCallObj.SignalEvents := -1;
  fCallObj.AsyncMode := 0; // -1;
  fCallObj.EnableDigitDetection := -1;
  fCallObj.EnableExtendedToneDetection := -1;
  fCallObj.VoiceEnableEchoCanceler := -1;
  fCallObj.LocalNumber:='0815';

  // Event-Wrapper Objekt erzeugen und verbinden (EventSink)
  fDivaCallEvents := TDIVASDKLibIDivaCallEvents.Create(nil);
  fDivaCallEvents.Connect(fCallObj);

  // Ereignisbehandlungsroutinen zuweisen
  fDivaCallEvents.OnConnected := DivaCallEventsConnected;
  fDivaCallEvents.OnDisconnected := DivaCallEventsDisconnected;
  fDivaCallEvents.OnToneReceived := DivaCallEventsToneReceived;

  Resume;
end;

destructor TWorkerThread.Destroy;
begin
 fDivaCallEvents.Disconnect;
 fDivaCallEvents.Free;
 fCallObj:=nil;
 CoUninitialize;
 inherited destroy;
end

procedure TWorkerThread.DoExecuteJob(ajob: TJob);
begin

  if aJob = nil then exit;

  // Showmessage(inttostr(fCallObj.Callstate));

  LogM(form1.log, GetCallResultCodesS(fCallObj.Connect(aJob.Rufnummer, DivaCallType_Voice)));

end;
Wenn Jobs zur Jobliste hinzugefügt werden wird TWorkerThread.DoExecuteJob aufgerufen. Sobald ich dort versuche auf fCallObj zuzugreifen, erscheint die o.a. Fehlermeldung (einmal pro Thread der einen Job übernimmt). Im Debugger kann man am Pointer von "fCallObj" sehen, das fCallObj in jedem Thread auf eine eigene Instanz von IDivaCall verweist.

Für Vorschläge (oder bessere Lösungen) bin ich dankbar. Im Moment steckt ich etwas fest.

Das SDK ist kostenlos.
Die importierte Typenbibliothek und die Event-Implementation (von EventSink) hänge ich mit in die Anlage.


Danke und schöne Grüße,
Jens

:hi:

Bernhard Geyer 4. Jan 2006 13:38

Re: COM Objekte in Threads. Wie geht das richtig ?
 
Du must deine Interface-Zeiger "Marshalen" wenn Sie von mehreren Threads verwendet werden.

jensw_2000 4. Jan 2006 14:02

Re: COM Objekte in Threads. Wie geht das richtig ?
 
Zitat:

Zitat von Bernhard Geyer
Du must deine Interface-Zeiger "Marshalen" wenn Sie von mehreren Threads verwendet werden.

Danke, das sieht vielversprechend aus.

Schöne Grüße,
Jens
:hi:

jensw_2000 4. Jan 2006 21:49

Re: COM Objekte in Threads. Wie geht das richtig ?
 
Es läuft.

Ich rufe im Mainthread (Initialization Abschnitt) und im Constructor der einzelnen WorkerThreads CoInitializeEx(nil, COINIT_MULTITHREADED) auf. Den Rest musste ich nicht verändern.

Hat diese Variante entscheidende Nachteile gegenüber CoMarshalInterThreadInterfaceInStream und Co. ?


Schöne Grüße,
Jens
:hi:


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:49 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz