Einzelnen Beitrag anzeigen

jensw_2000
(Gast)

n/a Beiträge
 
#1

Eventhandler für asynchron arbeitendende Objekte

  Alt 9. Jan 2008, 10:52
Verständnisfrage:

Ich habe eine Wrapper-Klasse für ein COM Object gebaut, das asynchron arbeitet.

Vereinfacht sieht die Klasse so aus:

Delphi-Quellcode:
Type
  TCallhandler = class;

  TCallhandlerStateChangeEvent = procedure(Sender:TCallhandler; aCallstate:APICallstateEnum);
  
  TCallhandler = class(TComponent)
  private
    FCallhandlerStateChangeEvent: TCallhandlerStateChangeEvent;
    FCurrentAPICallstate:APICallstateEnum;
    FAPICallEvents :TAPICallEvents
    FAPICallObj:IDivaCall; << das COM Object aus einer API
    procedure OnAPICallstateChange(aCallstate:APICallstateEnum); // wird über ein Sink Object des COM Objectes asynchron ausgelöst
  public
    constructor ...
    destructor ...
    property Callstate:APICallstate
             read FCurrentCallstate;
    property OnCallhandlerStateChange:TCallhandlerStateChangeEvent
             read FCallhandlerStateChangeEvent write FCallhandlerStateChangeEvent;
  end;

{ TCallhandler }
procedure TCallhandler.OnCallhandlerStateChange(aCallstate:APICallstateEnum);
begin
  FCurrentAPICallstate := aCallstate;
  if assigned(FCallhandlerStateChangeEvent) then
    FCallhandlerStateChangeEvent(self,FCurrentAPICallstate);
end;
Ich habe in einem Projekt 120 Instanzen dieses Callhandlers in einer abgeleiteten ObjectList zusammengefasst.

Delphi-Quellcode:
Type
  TCallhandlerGroup = class(TObjectList)
  private
    FSumIdle:integer;
    FSumConnecting:integer;
    FSumConnected:integer;
    procedure OnCallhandlerChange(aCallhandler:TCallhandler; aCallstate:APICallstateEnum);
    procedure UpdateCounters(Sender:TObject);
    ...
  public
    procedure GetUsageCounters(var callhandlerCount,idle,connecting,connected:intger);
    ...
  end;

{ TCallhandlerGroup }
procedure TCallhandlerGroup.AddCallhandler(Sender:TObject);
  var tmpCallhandler:TCallhandler;
begin
    tmpCallhandler:=TCallhandler.create(self);
    ...
    tmpCallhandler.OnCallhandlerStateChange := OnCallhandlerChange;
    ...
end;

procedure TCallhandlerGroup.OnCallhandlerChange(aCallhandler:TCallhandler; aCallstate:APICallstateEnum);
begin
   ...
   UpdateCounters;
   ...
end;

procedure TCallhandlerGroup.UpdateCounters(Sender:TObject);
  var i: integer;
begin
  FSumIdle:=0;
  FSumConnecting:=0;
  FSumConnected:=0;

  for i:= Items.count -1 downto 0 do
  begin
     with TCallhandler(Items[i]) do
     begin
       case Callstate of
         csIdle: inc(FSumIdle);
         csConnecting: inc(FSumConnecting);
         csConnected: inc(FSumConnected);
       end;
     end;
  end;
end;

procedure TCallhandlerGroup.GetUsageCounters(var callhandlerCount,idle,connecting,connected:intger);
begin
  callhandlerCount := count; // Items.count der ObjectList
  idle := FSumIdle
  connecting := FSumConnecting;
  connected := FSumConnected;
end;

Selbst auf die Gefahr hin, das ich mich oben bein skizzieren der Klassen vertippt habe.
Das System läuft mit 2 Callhandlern stabil.

Leider habe ich zuhause keine Möglichkeit das System mit 120 Kanälen (Callhandlern) zu testen.
Wenn die Software beim Kunden installiert wird sollte Sie natürlich nicht gleich abrauchen

Alle Instanzen laufen im Haup-Thread der Applikation.

Daher hier ein paar Fragen zur Sicherheit:

Kann der System Probleme bekommen :
a) wenn "UpdateCounters" den Callstate des Callhandler zählt während des Eventhandler "TCallhandler.OnAPICallstateChange" (asynchron ausgelöst vom COM Object) den Status des Callhandlers setzt? (also ggf. Exception weil Leseversuch während Schreibzugriff ?)

b) das die Ergebnisse "GetUsageCounters" nicht immer stimmen, weil ein "TCallhandler.OnAPICallstateChange" den Callstate eines Callhandlers ändert, währens UpdateCounters die Nutzung ermittelt ?

c) wenn ich hypothetisch die monentane Auslastung für Statistikzwecke in einen TDataset schreiben möchte ...
Ist es z.B. möglich, dass GetUsageCounters 2x zur selben Zeit ausgeführt wird, weil 2 Callhandler gleichzeitig ihre Statusänderung über den Eventhandler "FCallhandlerStateChangeEvent" publizieren wollen? Falls ja würde ich Probleme erwarten, wenn ein Callhandler grade den TDataset in den Edit-Modus setzen will, während ein anderer noch in Bearbeitung hat.


Wenn es keine Möglichkeit gibt, das ganze zu sauber zu "entkoppeln", dann richte ich lieber Pro Callhandler einen Thread ein, und synchronisiere die Sachen über TCriticalSection bzw. Synchronize ...



Schöne Grüße,
Jens
  Mit Zitat antworten Zitat