2013-01-25 18 views
5

, Delphi ile 10 Indy 9 Geçiş.görünüşte çok değişti gibi ben Indy 10.</p> <p>Oldukça acı verici için Indy 9 Bir Delphi uygulama güncellenirken sürecinde olduğum TIdSchedulerOfThreadPool başlatma

Tek adımda takılıyorum.

İşte (ile çalışan Indy 9) eski koddur:

Bir Konu Havuz oluşturulur ve havuzun her iş parçacığı başlatıldı ve ardından başladı. Her bir iş parçacığı indy bir http istemci oluşturur (ancak burada önemli değil).

TUrlThread = class(TIdThread) 

... 

var 
    i: Integer; 
begin 
    // create the Pool and init it 
    Pool   := TIdThreadMgrPool.Create(nil); 
    Pool.PoolSize := Options.RunningThreads; 
    Pool.ThreadClass:= TUrlThread; 

    // init threads and start them 
    for i := 1 to Options.RunningThreads do 
    begin 
    with (Pool.GetThread as TUrlThread) do 
    begin 
     Index  := i; 
     Controler := Self; 
     Priority := Options.Priority; 
     Start; 
    end; 
    end; 

TIdThreadMgrPool sınıf

Indy 10.

Bir değişimi ve TIdSchedulerOfThreadPool kazanan, benziyor ama çalışan alamayan için baktım ile gitti. İşte

modifiye (Indy 10) kodudur:

TUrlThread = class(TIdThreadWithTask) 

... 

var 
    i: Integer; 
begin 
    // create the Pool and init it 
    Pool   := TIdSchedulerOfThreadPool.Create(nil); 
    Pool.PoolSize := Options.RunningThreads; 
    Pool.ThreadClass:= TUrlThread; 

    // init threads and start them 
    for i := 1 to Options.RunningThreads do 
    begin 
    with (Pool.NewThread as TUrlThread) do 
    begin 
     Index  := i; 
     Controler := Self; 
     Priority := Options.Priority; 
     Start; 
    end; 
    end; 

Burada bir erişim ihlali özel olsun (bu Indy kodudur):

procedure TIdTask.DoBeforeRun; 
begin 
    FBeforeRunDone := True; 
    BeforeRun; 
end; 

FBeforeRunDone sıfırdır.

cevap

7

TIdSchedulerOfThreadPoolTIdThreadMgrPool 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.

İlgili konular