TIdSchedulerOfThreadPool
TIdThreadMgrPool
için Indy 10'un yerine geçtiğini biliyorsunuz. Ancak, dikkate almamanız, TIdScheduler
mimarisinin TIdThreadMgr
mimarisinden biraz farklı olmasıdır.
Indy 10, TIdThreadWithTask
kendi kendine çalışmıyor. Adından da anlaşılacağı gibi, TIdThreadWithTask
iplik ile bağlantılı olur (TIdPeerThread
Indy 10'in yerine geçer gibi TIdContext
) bir TIdTask
türetilmiş nesne bir görev gerçekleştirir. Konuları gerçekleştirmeleri için görev vermeden konuları çalıştırıyorsunuz, bu yüzden çökmeler yaşıyorsunuz. Start()
'u manuel olarak çağırmak için, önce tabanlı bir nesne oluşturup TIdThreadWithTask.Task
özelliğine atamanız gerekir. TIdTCPServer
bir TIdThreadWithTask
nesneye bağlı bir TIdYarn
nesne oluşturmak için TIdScheduler.AcquireYarn()
arayarak, ardından TIdContext
nesnesi oluşturur ve daha sonra üzerine Start()
çağırmadan önce kendi Task
özelliğini atamak TIdThreadWithTask
erişmek için TIdYarn
kullandığı, TIdScheduler.StartYarn()
onu geçtiğini işler. Bununla birlikte, tüm kayıp değildir. Indy 9 ve 10'un her ikisinde de, başlamak için el ile TIdThread.Start()
'u aramanız gerekmez. TIdTCPServer
, yeni bir istemci bağlantısını kabul ettikten sonra, ThreadMgr
/Scheduler
'dan bir iş parçacığı almayı ve istemci bağlantısını iş parçacığıyla ilişkilendirmeyi kabul eder. İplik özelliklerini gerçekten iş parçacığını hemen çalıştırmadan gerektiği gibi başlatabilirsiniz. Özellikler, iş parçacıklarının daha sonraki bir zamanda yayınlanmaya başladığı ilk seferde yürürlüğe girer.
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;
:
bu deneyin.
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;
Şimdi, bununla birlikte, dikkat etmeniz gereken son bir şey. Indy 9 ve 10'un her ikisinde de, iş parçacığı bittiğinde havuza geri yerleştirilemez ve başlangıç kodunuz çalıştırıldıktan sonra havuza yeni iş parçacıkları eklenebilir. PoolSize
, havuzda tutulacak minimum sayıdır, mutlak bir sayı değildir. Sunucuya PoolSize
müşteri sayısı bağlanabilir ve ihtiyaç duydukları anda bunlar için daha fazla iş parçacığı oluşturabilir, böylece başlatma kodunuzu atlayabilirsiniz. Her iki sürümde, iş parçacığı initalize etmek için en iyi yer TUrlThread
yapıcısındadır. Controler
işaretçinizi, gerektiğinde kurucunun erişebileceği bir yerde saklayın. Ve her iş parçacığına bir Index
atamak anlamlı değildir, çünkü havuzdaki iş parçacıklarının sırası zamanla dinamik olarak değişir. Aslında, el ile başlatma kodunuz aslında her iki sürümde başka bir nedenden dolayı yanlış onaylamadır. Hem TIdThreadMgrPool.GetThread()
hem de TIdSchedulerOfThreadPool.NewThread()
, yeni iş parçacığını havuza eklemez. Bir iş parçacığı çalışmayı durdurduğunda ve yeniden iş parçacığı kaydetmek için yer olduğunda ve ayrıca yalnızca TIdTCPServer
başlatıldığında Indy 10'da, iş parçacığı hem Indy 9 hem de 10'daki havuza eklenir. Yani aslında aslında hiçbir şey yapmıyor ve havuz tarafından izlenmiyorlar. Başlatma kodunuzu her iki sürümde yeniden tasarlamanın tüm nedenleri, böylece iş parçacığı, bunları oluşturmak için mimariye girmekten çok, normal koşullar altında oluşturulduklarında kendilerini başlatır.