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