2013-01-25 25 views
5

मैं, इंडी 10प्रवास के, TIdSchedulerOfThreadPool प्रारंभ

यह काफी दर्दनाक है करने के लिए इंडी 9 से एक डेल्फी ऐप्लिकेशन को अपडेट करने की प्रक्रिया में हूँ के रूप में जाहिरा तौर पर बहुत बदल गया है।

मैं एक कदम पर अटक गया हूं।

यहाँ पुराने कोड (के साथ काम करने इंडी 9) है:

एक धागा पूल बनाया गया है और पूल के हर धागा आरंभ नहीं हो जाता है और फिर शुरू कर दिया। व्यक्तिगत थ्रेड एक इंडी http क्लाइंट बनाते हैं (लेकिन इससे कोई फर्क नहीं पड़ता)।

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 वर्ग इंडी 10

मैं एक प्रतिस्थापन और TIdSchedulerOfThreadPool एक विजेता, की तरह दिखता है, लेकिन मैं यह नहीं चल रहा प्राप्त कर सकते हैं के लिए देखा है के साथ चला गया है।

यहाँ संशोधित (इंडी 10) कोड है:

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; 

मैं एक पहुँच उल्लंघन अपवाद यहाँ प्राप्त (इस इंडी कोड है):

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

FBeforeRunDone नहीं के बराबर है।

उत्तर

7

आप सही हैं कि TIdSchedulerOfThreadPoolTIdThreadMgrPool के लिए इंडी 10 का प्रतिस्थापन है। हालांकि, आप जो ध्यान में नहीं ले रहे हैं वह यह है कि TIdScheduler आर्किटेक्चर TIdThreadMgr आर्किटेक्चर से थोड़ा अलग है।

इंडी 10, TIdThreadWithTask में स्वयं संचालित नहीं होता है। जैसा कि इसके नाम से तात्पर्य है, TIdThreadWithTaskकार्य निष्पादित करता है, जो TIdTask है - ऑब्जेक्ट ऑब्जेक्ट (जैसे TIdContext, जो TIdPeerThread के लिए इंडी 10 का प्रतिस्थापन है) जो धागे से जुड़ा हुआ है। आप उन्हें काम करने के बिना धागे चला रहे हैं, यही कारण है कि आप दुर्घटनाओं का सामना कर रहे हैं। Start() मैन्युअल रूप से कॉल करने के लिए, आपको पहले -आधारित ऑब्जेक्ट को TIdThreadWithTask.Task संपत्ति पर बनाने और असाइन करने की आवश्यकता है। TIdTCPServer संभालती है कि TIdScheduler.AcquireYarn() बुला एक TIdYarn उद्देश्य यह है कि एक TIdThreadWithTask वस्तु से जुड़ा हुआ है बनाने के लिए द्वारा, तो एक TIdContext वस्तु बनाता है और TIdScheduler.StartYarn() को पास कर देता है, जो फिर बुला उस पर Start() से पहले अपने Task संपत्ति आवंटित करने के लिए TIdThreadWithTask तक पहुँचने के लिए TIdYarn उपयोग करता है।

हालांकि, सभी खो नहीं गए हैं। इंडी 9 और 10 दोनों में, आपको वास्तव में शुरू करने के लिए मैन्युअल रूप से TIdThread.Start() पर कॉल नहीं करना चाहिए। TIdTCPServer आपके लिए एक नया क्लाइंट कनेक्शन स्वीकार करने के बाद, ThreadMgr/Scheduler से थ्रेड प्राप्त करने और क्लाइंट कनेक्शन को थ्रेड से जोड़कर संभालता है। आप वास्तव में थ्रेड को तुरंत चलाने के बिना आवश्यकतानुसार अपने थ्रेड गुणों को प्रारंभ कर सकते हैं। पहली बार सूत्रों को बाद में चलने लगेंगे जब गुण प्रभावी होंगे।

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; 

अब, इसके साथ, एक आखिरी चीज देखने के लिए। इंडी 9 और 10 दोनों में, समाप्त होने पर धागे को पूल में वापस नहीं रखा जा सकता है, और प्रारंभिक कोड चलाने के बाद पूल में नए थ्रेड जोड़े जाने के लिए संभव है। PoolSize पूल में रखने के लिए धागे की न्यूनतम संख्या है, पूर्ण गणना नहीं। PoolSize से अधिक ग्राहक सर्वर से कनेक्ट हो सकते हैं और जब आवश्यक हो, तो यह खुशी से उनके लिए अधिक धागे बनाएगा, इस प्रकार आपके प्रारंभिक कोड को छोड़कर। दोनों संस्करणों में, आपके धागे को निष्क्रिय करने के लिए सबसे अच्छी जगह TUrlThread कन्स्ट्रक्टर में है। अपने Controler कहीं कहीं पॉइंटर स्टोर करें कि जब आवश्यक हो तो कन्स्ट्रक्टर इसे एक्सेस कर सकता है। और प्रत्येक धागे में Index असाइन करने का अर्थ नहीं है क्योंकि पूल में धागे के क्रम समय के साथ गतिशील रूप से बदलते हैं।

वास्तव में, आपका मैन्युअल प्रारंभिक कोड वास्तव में किसी अन्य कारण से दोनों संस्करणों में गलत दृष्टिकोण है। TIdThreadMgrPool.GetThread() और TIdSchedulerOfThreadPool.NewThread() दोनों पूल में नया धागा बिल्कुल न जोड़ें। थ्रेड को इंडी 9 और 10 दोनों में पूल में जोड़ा जाता है जब थ्रेड चलना बंद कर देता है और धागे को पुन: उपयोग के लिए सहेजने के लिए जगह होती है, और इसके अलावा इंडी 10 में केवल TIdTCPServer शुरू हो रही है। तो आप वास्तव में ऐसे धागे बना रहे हैं जो वास्तव में कुछ भी नहीं कर रहे हैं और पूल द्वारा ट्रैक नहीं किए जा रहे हैं। दोनों संस्करणों में अपने प्रारंभिक कोड को फिर से डिज़ाइन करने के लिए और भी अधिक कारण है, इसलिए जब वे सामान्य रूप से उन्हें बनाने के लिए आर्किटेक्चर में हैकिंग करने के बजाए सामान्य परिस्थितियों में बनाए जाते हैं तो धागे स्वयं को प्रारंभ करते हैं।