2011-06-15 16 views
12

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

कोई सुझाव?

+0

किस प्रकार के धागे? कुछ पुस्तकालय हैं जो थ्रेडिंग कार्यक्षमता प्रदान करते हैं। – Blender

+0

दुर्भाग्यवश, कनेक्शन के लिए अलग (POSIX) धागे का उपयोग करते समय यह केवल हिमशैल की नोक है। इसके बजाए गैर-अवरुद्ध I/O का उपयोग करने पर विचार करें (उदाहरण के लिए, ट्विस्टेड का उपयोग करना।) –

+0

थ्रेड को स्वयं को समाप्त करने की आवश्यकता है (या ऐसा करने के लिए कहा जाए)। क्या आप उन्हें अवरुद्ध नहीं कर सकते हैं, इसलिए अगर वे संकेत दिए गए तो वे बाहर निकल सकते हैं? (मतदान या जो कुछ भी) –

उत्तर

7

इस पर काम करने का कोई अच्छा तरीका नहीं है, खासकर जब थ्रेड अवरुद्ध हो रहा है।

मेरे पास एक समान समस्या थी (Python: How to terminate a blocking thread) और मेरे धागे को रोकने में सक्षम एकमात्र तरीका अंतर्निहित कनेक्शन को बंद करना था। जिसके परिणामस्वरूप थ्रेड में वृद्धि हुई और अपवाद को अवरुद्ध कर दिया गया और फिर मुझे स्टॉप फ्लैग और क्लोज़ की जांच करने की अनुमति मिली।

उदाहरण कोड:

class Example(object): 
    def __init__(self): 
     self.stop = threading.Event() 
     self.connection = Connection() 
     self.mythread = Thread(target=self.dowork) 
     self.mythread.start()  
    def dowork(self): 

     while(not self.stop.is_set()): 
      try: 
        blockingcall()   
      except CommunicationException: 
        pass 
    def terminate(): 
     self.stop.set() 
     self.connection.close() 
     self.mythread.join() 

नोट करने के लिए आमतौर पर आम तौर पर संचालन ब्लॉक कर रहा है एक और बात समय समाप्त की पेशकश। यदि आपके पास वह विकल्प है तो मैं इसका उपयोग करने पर विचार करूंगा।

एक धागा एक "डेमॉन सूत्र" के रूप में चिह्नित किया जा सकता है: मेरी अंतिम टिप्पणी है कि आप हमेशा pydoc से deamonic लिए धागा,

सेट कर सकते है। इस झंडे का महत्व यह है कि पूरे पायथन प्रोग्राम निकलता है जब केवल डेमॉन धागे छोड़े जाते हैं। प्रारंभिक मान बनाने के धागे से विरासत में मिला है। ध्वज डेमॉन संपत्ति के माध्यम से सेट किया जा सकता है।

+2

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

+0

+1 मैं 100% सहमत हूं, लेकिन कुछ बार आप नहीं कर सकते हैं ...; ( – Nix

+0

दुर्भाग्यवश सच है, हालांकि शायद ही कभी दायर किए गए रिकॉर्डस्क्रिप्टर्स पर आप काम कर रहे हैं। (वास्तव में समस्याग्रस्त मामले बाहरी पुस्तकालयों को अवरुद्ध कर रहे हैं जिनके पास नहीं है संचालन में बाधा डालने का तरीका: पी) –

0

इन उत्तरों देखें:

Python SocketServer
How to exit a multithreaded program?

मूल रूप से

, सॉकेट की पठनीयता के लिए जाँच करने के लिए एक समय समाप्ति के साथ select() का उपयोग करके recv() पर ब्लॉक नहीं है, और पोल एक झंडा जब छोड़ने select() बार बाहर।

+0

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

+0

इस तरह धागे की दुनिया है ... – theorifice

1

इसके अलावा, धागे पंजीकृत नहीं कर सकता संकेत संचालकों

धागे को मारने के लिए

सिग्नल संभावित भयानक है, विशेष रूप से सी में, खासकर यदि आप धागे के हिस्से के रूप में स्मृति को आबंटित है, क्योंकि यह मुक्त नहीं किया जाएगा जब वह विशेष धागा मर जाता है (क्योंकि यह प्रक्रिया के ढेर से संबंधित है)। सी में कोई कचरा संग्रह नहीं है, इसलिए यदि वह सूचक स्कोप से बाहर हो जाता है, तो यह गुंजाइश से बाहर हो गया है, स्मृति आवंटित बनी हुई है। तो बस उस से सावधान रहें - केवल सी में ऐसा ही करें यदि आप वास्तव में सभी धागे को मारने जा रहे हैं और प्रक्रिया को समाप्त कर रहे हैं ताकि स्मृति को ओएस को वापस सौंप दिया जा सके - उदाहरण के लिए थ्रेडपूल से थ्रेड जोड़ना और निकालना आपको एक स्मृति रिसाव देगा।

समस्या यह है कि जब मैं इन बच्चों के धागे को बंद करना चाहता हूं तो वे सभी इनपुट पर अवरुद्ध हो रहे हैं।

काफी हद तक मैं हाल ही में एक ही चीज़ के साथ लड़ रहा हूं।समाधान सचमुच बिना किसी टाइमआउट के अवरुद्ध कॉल न करें। तो, उदाहरण के लिए, क्या आप आदर्श है चाहता हूँ:

def threadfunc(running): 

    while running: 
     blockingcall(timeout=1) 

जहां चल नियंत्रित धागे से पारित हो जाता है - मैं सूत्रण उपयोग नहीं किया है, लेकिन मैं और बहु ​​का इस्तेमाल किया है और इस के साथ आप वास्तव में एक Event() वस्तु पारित करने के लिए की जरूरत है is_set() देखें। लेकिन आपने डिजाइन पैटर्न के लिए कहा, यह मूल विचार है।

फिर, जब आप समाप्त करने के लिए इस सूत्र चाहते हैं, आप चलाएँ:

running.clear() 
mythread.join() 

और अपने मुख्य थ्रेड तो अपने ग्राहक धागा अपने आखिरी कॉल संभाल, और वापस जाने के लिए अनुमति चाहिए, और पूरे कार्यक्रम अच्छी तरह से ऊपर परतों ।

यदि आपके पास टाइमआउट के बिना अवरुद्ध कॉल है तो आप क्या करते हैं? एसिंक्रोनस विकल्प का उपयोग करें, और नींद (जैसा कि आपको किसी भी विधि को थ्रेड को निलंबित करने की आवश्यकता है, ताकि आप कताई नहीं कर रहे हों) यदि आपको आवश्यकता हो। इसके चारों ओर कोई और रास्ता नहीं है।

संबंधित मुद्दे