2011-02-03 11 views
61

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

कुछ समय पर मैं दोनों वस्तुओं से छुटकारा पाना चाहता हूं। उनमें से कोई संकेत या कुछ भी नहीं। मैं उन्हें जाना चाहता हूँ। ठीक है, मैंने सोचा, मैं

delete obj1; delete obj2; 

इस्तेमाल करेंगे लेकिन मैं सच में कर सकते हैं? ~ QObject के लिए चश्मा कहते हैं:

एक QObject हटाया जा रहा लंबित घटनाओं एक दुर्घटना का कारण बन सकती वितरित होने की प्रतीक्षा कर रहे हैं।

'लंबित घटनाएं' क्या हैं? क्या इसका मतलब यह हो सकता है कि जब मैं अपना delete कह रहा हूं, तो पहले से ही कुछ लंबित घटनाएं वितरित की जा रही हैं और वे एक दुर्घटना का कारण बन सकते हैं और मैं वास्तव में जांच नहीं सकता कि कोई है या नहीं?

तो चलो कहते हैं कि मैं कॉल:

obj1->deleteLater(); obj2->deleteLater(); 

सुरक्षित होने के लिए।

लेकिन, क्या मैं वास्तव में सुरक्षित हूं? deleteLater एक ऐसी घटना को जोड़ता है जो नियंत्रण के दौरान मुख्य लूप में संभाला जाएगा। obj1 या obj2 के लिए पहले से ही कुछ लंबित घटनाएं (सिग्नल) हो सकती हैं, मुख्य लूप में हटाने से पहले प्रतीक्षा करने के लिए प्रतीक्षा किया जा रहा है? यह बहुत दुर्भाग्यपूर्ण होगा। मैं 'कुछ हद तक हटाई गई' स्थिति के लिए कोड जांच लिखना नहीं चाहता हूं और मेरे सभी स्लॉट में आने वाले सिग्नल को अनदेखा करना चाहता हूं।

+3

'obj-> डिस्कनेक्ट() की तरह दिखता है; obj-> deleteLater(); 'जाने के लिए सही तरीका है: – stach

उत्तर

59

QObjects हटाया जा रहा है आम तौर पर सुरक्षित है (यानी सामान्य व्यवहार में, वहाँ रोग मामलों मैं एटीएम के बारे में पता नहीं कर रहा हूँ हो सकता है), यदि आप दो बुनियादी नियमों का पालन:

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

  • इसी तरह, किसी ऑब्जेक्ट के ईवेंट हैंडलर से सिंक्रनाइज़ रूप से कोड में किसी ऑब्जेक्ट को कभी भी हटाएं। जैसे अपने SomeWidget :: fooEvent() में कुछ विधियों को हटाएं या उन तरीकों/स्लॉट्स में जिन्हें आप वहां से कॉल नहीं करते हैं। इवेंट सिस्टम पहले से हटाए गए ऑब्जेक्ट पर काम करना जारी रखेगा -> क्रैश।

दोनों को ट्रैक करने के रूप में बैकट्रैस आमतौर पर अजीब लग रही है (दुर्घटना की तरह, जबकि एक पॉड सदस्य चर एक्सेस करने वाले), खासकर जब आप संकेत/स्लॉट चेन जटिल है, जहां एक हटाए जाने के लिए कई कदम नीचे मूल रूप से हो सकता है मुश्किल हो सकता है हटाए गए ऑब्जेक्ट से सिग्नल या ईवेंट द्वारा शुरू किया गया।

ऐसे मामले deleteLater() के लिए सबसे आम उपयोग केस हैं। यह सुनिश्चित करता है कि ईवेंट इवेंट लूप पर नियंत्रण लौटने से पहले वर्तमान ईवेंट पूरा किया जा सकता है, जो तब ऑब्जेक्ट को हटा देता है।एक और, मुझे अक्सर एक बेहतर तरीका मिलता है जो कतारबद्ध कनेक्शन/QMetaObject :: invokeMethod (..., Qt :: QueuedConnection) का उपयोग करके पूरी कार्रवाई को रोकता है।

2

जहां तक ​​मुझे पता है, यह मुख्य रूप से एक मुद्दा है यदि वस्तुएं विभिन्न धागे में मौजूद हैं। या हो सकता है कि आप वास्तव में संकेतों को संसाधित कर रहे हों।

अन्यथा एक QObject को हटाने से पहले सभी सिग्नल और स्लॉट डिस्कनेक्ट हो जाएंगे और सभी लंबित घटनाओं को हटा दिया जाएगा। डिस्कनेक्ट करने के लिए कॉल के रूप में() करेंगे।

13

आप Delta Object Rules जो इस में कहा गया है में से एक के बारे में पढ़ अपने प्रश्न का उत्तर पा सकते हैं:

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

टुकड़ा:

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

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

आम तौर पर मैं हर क्यूटी डेवलपर के लिए डेल्टा वस्तु नियम के रूप में अनिवार्य पढ़ने में मानते हैं। यह उत्कृष्ट पढ़ने सामग्री है।

+1

आप कीट के लिए लिंक का पालन करें, तो आप आगे पढ़ने, उदा कि पृष्ठ पर लिंक का पालन करना होगा के लिए लिंक का पालन करें 'सिग्नल सुरक्षित।' लिंक से पहले पृष्ठ संदर्भ के बिना समझना कठिन है। मेरी दूसरी परिदृश्य के बारे में (मैं विंडोज पर PyQt का उपयोग कर बाहर निकलने पर एक दुर्घटना का पीछा करते हुए कर रहा हूँ, मेरे ऐप भी किसी भी वस्तुओं को हटाने नहीं है, लेकिन मुझे उम्मीद है कि एक प्रकार का गुबरैला के लिए लिंक अंतर्दृष्टि प्रदान करते हैं।) – bootchk

19

आपके निर्दिष्ट दस्तावेज़ों की अगली दो पंक्तियां उत्तर देती हैं।

~QObject से

,

एक QObject हटाया जा रहा लंबित घटनाओं एक दुर्घटना का कारण बन सकती वितरित होने की प्रतीक्षा कर रहे हैं। आप को QObject को सीधे हटा नहीं देना चाहिए यदि यह वर्तमान में निष्पादित करने वाले किसी भिन्न थ्रेड में मौजूद है। इसके बजाय deleteLater() का उपयोग करें, जिससे घटना लंबित घटनाओं को सभी लंबित घटनाओं को वितरित करने के बाद ऑब्जेक्ट को हटा दिया जाएगा।

यह विशेष रूप से हमें अन्य धागे से हटाने के लिए नहीं करने के लिए कहते हैं। के बाद से आप एक ही लड़ी आवेदन है, यह QObject हटाना सुरक्षित है।

अन्यथा, यदि आपको इसे बहु-थ्रेडेड वातावरण में हटाना है, तो deleteLater() का उपयोग करें जो सभी घटनाओं की प्रसंस्करण के बाद आपके QObject को हटा देगा।

+5

क्या? एक वस्तु में स्लॉट के बाद भी मैं इस पर deleteLater फोन कहा जा सकता है? – stach

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