Sie haben Recht, dass TIdSchedulerOfThreadPool
der Indy 10 Ersatz für TIdThreadMgrPool
ist. Was Sie jedoch nicht berücksichtigen, ist, dass die TIdScheduler
Architektur ein wenig anders ist als die TIdThreadMgr
Architektur.
In Indy 10, TIdThreadWithTask
funktioniert nicht von selbst. Wie der Name andeutet, führt TIdThreadWithTask
einen Task aus, der ein TIdTask
-abgeleitetes Objekt ist (wie TIdContext
, das Indy 10 ersetzt für TIdPeerThread
), das mit dem Thread verknüpft wird. Sie führen Threads aus, ohne ihnen Aufgaben zu geben, weshalb Sie abstürzen. Um Start()
manuell aufzurufen, müssen Sie zuerst ein TIdTask
-basiertes Objekt erstellen und der TIdThreadWithTask.Task
-Eigenschaft zuweisen. TIdTCPServer
Griffe dass TIdScheduler.AcquireYarn()
durch den Aufruf eines TIdYarn
-Objekt zu erstellen, die zu einem TIdThreadWithTask
Objekt verknüpft ist, erstellt dann ein TIdContext
Objekt und übergibt sie an TIdScheduler.StartYarn()
, die die TIdYarn
verwendet die TIdThreadWithTask
zuzugreifen seine Task
Eigenschaft zuweisen, bevor dann Start()
auf sie anrufen.
Aber alles ist nicht verloren. Sowohl in Indy 9 als auch in 10 sollten Sie wirklich nicht TIdThread.Start()
manuell aufrufen, um damit zu beginnen. TIdTCPServer
behandelt dies nach dem Akzeptieren einer neuen Clientverbindung, beim Abrufen eines Threads von dessen ThreadMgr
/Scheduler
und beim Zuordnen der Clientverbindung zum Thread. Sie können Ihre Thread-Eigenschaften nach Bedarf initialisieren, ohne die Threads sofort auszuführen. Die Eigenschaften werden wirksam, wenn die Threads das erste Mal zu einem späteren Zeitpunkt ausgeführt werden.
starten:
TUrlThread = class(TIdThread)
...
var
i: Integer;
begin
// create the Pool and init it
Pool := TIdThreadMgrPool.Create(nil);
Pool.PoolSize := Options.RunningThreads;
Pool.ThreadClass:= TUrlThread;
Pool.ThreadPriority := Options.Priority;
// init threads and start them
for i := 1 to Options.RunningThreads do
begin
with (Pool.GetThread as TUrlThread) do
begin
Index := i;
Controler := Self;
end;
end;
.
TUrlThread = class(TIdThreadWithTask)
...
var
i: Integer;
begin
// create the Pool and init it
Pool := TIdSchedulerOfThreadPool.Create(nil);
Pool.PoolSize := Options.RunningThreads;
Pool.ThreadClass:= TUrlThread;
Pool.ThreadPriority := Options.Priority;
// init threads and start them
for i := 1 to Options.RunningThreads do
begin
with (Pool.NewThread as TUrlThread) do
begin
Index := i;
Controler := Self;
end;
end;
Nun, mit diesem gesagt, eine letzte Sache aufpassen. In Indy 9 und 10 ist es möglich, dass Threads nach Abschluss des Initialisierungscodes nicht mehr in den Pool zurückgesetzt werden und dass neue Threads zum Pool hinzugefügt werden. Die PoolSize
ist die minimale Anzahl der Threads im Pool, nicht eine absolute Anzahl. Mehr als PoolSize
Anzahl der Clients kann eine Verbindung mit dem Server herstellen, und es wird erfreulicherweise mehr Threads für sie zum Zeitpunkt ihrer Verwendung erstellen und damit Ihren Initialisierungscode umgehen. In beiden Versionen ist der beste Ort zum Initialisieren der Threads der TUrlThread
-Konstruktor. Speichern Sie Ihren Zeiger Controler
irgendwo, dass der Konstruktor es bei Bedarf erreichen kann. Und es ist nicht sinnvoll, jedem Thread einen Index
zuzuweisen, da sich die Reihenfolge der Threads im Pool dynamisch im Laufe der Zeit ändert.
Tatsächlich ist Ihr manueller Initialisierungscode tatsächlich in beiden Versionen aus einem anderen Grund der falsche Ansatz. Sowohl TIdThreadMgrPool.GetThread()
als auch TIdSchedulerOfThreadPool.NewThread()
fügen den neuen Thread dem Pool überhaupt nicht hinzu. Threads werden dem Pool in Indy 9 und 10 hinzugefügt, wenn ein Thread aufhört zu laufen, und es genügend Platz gibt, den Thread zur Wiederverwendung zu speichern, und zusätzlich in Indy 10 nur, wenn TIdTCPServer
gestartet wird. Sie erstellen also tatsächlich Threads, die gar nichts tun und nicht vom Pool verfolgt werden. Umso mehr Grund, Ihren Initialisierungscode in beiden Versionen neu zu entwerfen, damit sich Threads initialisieren, wenn sie unter normalen Bedingungen erstellt werden, anstatt sich in die Architektur zu hacken, um sie manuell zu erstellen.