2010-12-09 30 views
5

सुरक्षित रूप से फिर से शुरू हो रहा है इस प्रश्न में डेल्फी और एक्सई विशेष रूप से सस्पेंड और फिर से शुरू करने से वंचित है। मैंने अन्य पदों को पढ़ा है और मुझे अब तक एक समान उपयोग नहीं मिला है, इसलिए मैं आगे बढ़ने जा रहा हूं और चर्चा के लिए कहूंगा।स्वयं डेल्फी में एक थ्रेड को निलंबित कर रहा है जब इसकी आवश्यकता नहीं है और

क्या मैं जानना चाहता हूं कि थ्रेड को रोकने के लिए एक बेहतर तरीका है जब इसकी आवश्यकता नहीं है?

हमारे पास एक डेल्फी वर्ग है जिसे हमने वर्षों से उपयोग किया है जो मूल रूप से एक फीफो कतार है जो थ्रेडेड प्रक्रिया से जुड़ा हुआ है। कतार मुख्य थ्रेड पर डेटा ऑब्जेक्ट स्वीकार करती है और यदि थ्रेड निलंबित कर दिया जाता है तो यह फिर से शुरू हो जाएगा।

थ्रेड की निष्पादन प्रक्रिया के हिस्से के रूप में ऑब्जेक्ट कतार से बाहर हो गया है और धागे पर संसाधित किया गया है। आमतौर पर यह डेटाबेस लुकअप करना है।

प्रक्रिया के अंत में ऑब्जेक्ट की एक संपत्ति को अद्यतन किया गया है और मुख्य धागे के लिए उपलब्ध के रूप में चिह्नित किया गया है या किसी अन्य कतार में भेजा गया है। निष्पादन प्रक्रिया का आखिरी (अच्छी तरह से यह वास्तव में पहला है) चरण यह जांचना है कि कतार में कोई और चीजें हैं या नहीं। यदि यह जारी है, अन्यथा यह खुद को निलंबित कर देता है।

वे कुंजी केवल एकमात्र निलंबन कार्रवाई निष्पादित लूप के अंदर होती है जब यह पूरा हो जाती है, और सामान्य संचालन के दौरान केवल एक ही फिर से शुरू होता है जब कतार में एक नया आइटम रखा जाता है। अपवाद तब होता है जब कतार वर्ग समाप्त हो रहा है।

फिर से शुरू करने वाला फ़ंक्शन ऐसा कुछ दिखता है।

process TthrdQueue.MyResume(); 
    begin 
    if Suspended then begin 
     Sleep(1); //Allow thread to suspend if it is in the process of suspending 
     Resume(); 
    end; 
    end; 

निष्पादित इस

process TthrdQueue.Execute(); 
    var 
    Obj : TMyObject; 
    begin 
    inherited; 
    FreeOnTerminate := true; 
    while not terminated do begin 
     if not Queue.Empty then begin 
     Obj := Pop(); 
     MyProcess(Obj); //Do work 
     Obj.Ready := true; 
     end 
     else 
     Suspend(); // No more Work 
    end; //Queue clean up in Destructor 
    end; 

के समान दिखता है TthrdQueue पुश ढेर में किसी अन्य वस्तु को जोड़ने के बाद नियमित कॉल MyResume। MyResume केवल तभी जारी किया जाता है जब थ्रेड निलंबित हो जाता है।

जब हम बंद करते हैं तो हम सत्य को समाप्त कर देते हैं और इसे निलंबित होने पर MyResume को कॉल करते हैं।

+0

मैं कोई विशेषज्ञ नहीं हूं लेकिन मैं अधिक सटीक नियंत्रण के लिए बस स्लीप (250) या सिग्नल ऑब्जेक्ट एंडवाइट (एमएसडीएन देखें) का उपयोग करता हूं। –

उत्तर

5

मैं TthrdQueue के निम्नलिखित कार्यान्वयन की सलाह देते हैं:

type 
    TthrdQueue = class(TThread) 
    private 
    FEvent: THandle; 
    protected 
    procedure Execute; override; 
    public 
    procedure MyResume; 
    end; 

implementation 

procedure TthrdQueue.MyResume; 
begin 
    SetEvent(FEvent); 
end; 

procedure TthrdQueue.Execute; 
begin 
    FEvent:= CreateEvent(nil, 
         False, // auto reset 
         False, // initial state = not signaled 
         nil); 
    FreeOnTerminate := true; 
    try 
    while not Terminated do begin 
     if not Queue.Empty then begin 
     Obj := Pop(); 
     MyProcess(Obj); //Do work 
     Obj.Ready := true; 
     end 
     else 
     WaitForSingleObject(FEvent, INFINITE); // No more Work 
    end; 
    finally 
    CloseHandle(FEvent); 
    end; 
end; 
+2

उन्होंने उल्लेख किया कि वह डेल्फी एक्सई पर हैं, इसलिए उनके पास पहले से ही जेनिक्स में टीटीएचडेड क्यूयू जेनेरिक क्लास तक पहुंच है। चयन इकाई। TThreadedQueue एक फीफो कतार है जिसमें धक्का और पॉपिंग करते समय थ्रेड सिंक्रनाइज़ करने की क्षमता होती है। – vcldeveloper

+1

हम अभी भी हमारे पुस्तकालयों में बहुत सारे डेल्फी 7 कोड का समर्थन करते हैं। लेकिन मैं भावी endevours के लिए TThreadedQueue देखेंगे। मुझे हमारे मौजूदा कोड को अपडेट करने में आसानी के लिए दिया गया समाधान पसंद है। –

+0

यह एक अच्छा समाधान की तरह दिखता है, लेकिन आप MyResume कहां जा रहे हैं? क्या कतार ऐसा करेगी? और कब? यह कैसे पता चलेगा कि कौन से धागे जागने हैं? या जैसे ही कतार के पीछे एक आइटम जोड़ा जाता है, आप बस सभी सोने के थ्रेड उठाएंगे। – GolezTrol

3

इसके बजाय धागा निलंबित की है, यह सोने के हैं। इसे कुछ प्रतीक्षा करने योग्य हैंडल पर अवरुद्ध करें, और जब हैंडल सिग्नल हो जाए, तो थ्रेड उठ जाएगा।

आपके पास घटनाओं, म्यूटेक्स ऑब्जेक्ट्स, सेमफोर, संदेश कतार, पाइप समेत प्रतीक्षा करने योग्य वस्तुओं के लिए कई विकल्प हैं।

मान लीजिए कि आप किसी ईवेंट का उपयोग करना चुनते हैं। इसे एक ऑटो-रीसेट ईवेंट बनाएं। जब कतार खाली होती है, तो ईवेंट की WaitFor विधि पर कॉल करें। जब कुछ और कतार को पॉप्युलेट करता है या छोड़ना चाहता है, तो इसे ईवेंट की SetEvent विधि पर कॉल करें।

मुझे पसंद है तकनीक ओएस संदेश कतार का उपयोग करना है। मैं आपके कतार वस्तु को संदेशों के साथ बदल दूंगा। फिर, एक मानक GetMessage पाश लिखें। जब कतार खाली है, तो यह स्वचालित रूप से एक नए संदेश की प्रतीक्षा करने के लिए अवरुद्ध हो जाएगा। समाप्ति अनुरोध को केवल एक और संदेश में बदलें। (TThread.Terminate विधि थ्रेड के साथ कुछ भी दिलचस्प करने के बाद बस एक बहुत उपयोगी काम नहीं है क्योंकि यह वर्चुअल नहीं है।)

+0

मुझे लगता है कि कतारों का समर्थन करने के लिए विंडोज का उपयोग करने का आपका क्या मतलब है। हम जो भी उपयोग कर रहे हैं वह बहुत सारे एक्सिसिटिंग कोड में है और अब पर्याप्त है। लेकिन मैं भविष्य में काम के लिए निश्चित रूप से इसे देख लूंगा, मुझे इसकी स्वचालित प्रकृति पसंद है। धन्यवाद। –

3

Delphi using condition variables में निर्माता-उपभोक्ता कतार के कार्यान्वयन की अनुमति देने के लिए एक लाइब्रेरी है। यह परिदृश्य वास्तव में चर्चा की गई उदाहरण है।

हालत चर का उत्कृष्ट उदाहरण निर्माता/उपभोक्ता समस्या है। एक या अधिक सूत्र कहा जाता उत्पादकों वस्तुओं का उत्पादन और उन्हें एक कतार में जोड़ें। उपभोक्ताओं (अन्य धागे) कतार से आइटम उत्पादन को हटाने के द्वारा आइटम खपत करते हैं।