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