Einzelnen Beitrag anzeigen

jensw_2000
(Gast)

n/a Beiträge
 
#1

COM Objekte in Threads. Wie geht das richtig ?

  Alt 4. Jan 2006, 14:28
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 ?


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

Angehängte Dateien
Dateityp: pas divasdklib_tlb_195.pas (112,4 KB, 5x aufgerufen)
Dateityp: pas divasdklibevents_915.pas (35,5 KB, 8x aufgerufen)
  Mit Zitat antworten Zitat