2012-08-24 33 views
5

के डेलेटेलटर से जुड़ा हुआ है, मैंने इस सवाल को पूछने से पहले बहुत कुछ सोचा है और बहुत सारे लेख पढ़े हैं। लेखों में से कोई भी मुझे उचित जवाब नहीं दिया।QThread समाप्त हुआ() QObject

http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/

QThread* thread = new QThread; 
Worker* worker = new Worker(); 
worker->moveToThread(thread); 
connect(worker, SIGNAL(error(QString)), this, SLOT(errorString(QString))); 
connect(thread, SIGNAL(started()), worker, SLOT(process())); 
connect(worker, SIGNAL(finished()), thread, SLOT(quit())); 
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater())); 
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); 
thread->start(); 

कार्यकर्ता वस्तु नया थ्रेड का संबंध है।

1> कार्यकर्ता समाप्त सिग्नल थ्रेड पर छोड़ने() को कॉल करेगा। यह थ्रेड के ईवेंट लूप को समाप्त कर देगा और थ्रेड समाप्त सिग्नल शुरू करेगा।

2> कार्यकर्ता समाप्त सिग्नल कार्यकर्ता हटाए गए Later() से जुड़ा हुआ है। डिलीटलाटर के अनुसार() प्रलेखन

** इस ऑब्जेक्ट को हटाने के लिए अनुसूची। ईवेंट लूप पर नियंत्रण लौटने पर ऑब्जेक्ट हटा दिया जाएगा। घटना पाश है> नहीं

जब इस समारोह कहा जाता है चल रहा है (उदाहरण के लिए deleteLater() QCoreApplication से पहले एक वस्तु :: कार्यकारी पर कहा जाता है()), वस्तु हटा दिया जाएगा एक बार घटना पाश शुरू कर दिया है।

ध्यान दें कि एक नया इवेंट लूप (उदा।, एक मोडल संवाद खोलकर) दर्ज करना और छोड़ना स्थगित हटाना नहीं करेगा; ऑब्जेक्ट को हटाने के लिए, नियंत्रण ईवेंट लूप पर वापस जाना चाहिए जिससे हटाएंटर() को कॉल किया गया था।

नोट: यह इस फ़ंक्शन को एक से अधिक बार कॉल करने के लिए सुरक्षित है; जब पहली आस्थगित विलोपन घटना वितरित किया जाता है, वस्तु के लिए बकाया घटनाओं घटना कतार से निकाल दिया जाता है। **

तो कोई eventloop है जब, के बाद से धागा पहले से ही बाहर निकलने जाता है और यह पहले से ही उठाया गया है समाप्त सिग्नल और हम अब एक ही धागे को फिर से शुरू नहीं करेंगे। इस मामले में deleteLater() को कभी भी संभाला नहीं जाएगा क्योंकि ईवेंट लूप मौजूद नहीं है और कार्यकर्ता ऑब्जेक्ट बिल्कुल हटाया नहीं जाएगा। क्या यह स्मृति रिसाव नहीं बनाता है।

connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater())); 
connect(worker, SIGNAL(finished()), thread, SLOT(quit())); 

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

ऊपर वर्णित आलेख लिंक में टिप्पणियों का समूह है। यहां तक ​​कि लेखक सवाल पूरी तरह से

उत्तर

2

QThread दूसरे शब्दों में संकेत

भेजने इसके समाप्त होने पर बाद QEvent :: DeferredDelete की एक घटना प्रकार के साथ एक QCoreApplication::sendPostedEvents करेंगे QThread एकत्रित करेगा जवाब देने में सक्षम नहीं था https://qt.gitorious.org/qt/qtbase/source/c657bb7b51115d6e1719166fb502bb0ca1dcf4e8:src/corelib/thread/qthread_win.cpp#L363-462

2
सभी लंबित deleteLaters
//! put the following code in constructor 
QThread *thread = new QThread; 
//! type of m_weakThread is QWeakPointer<QThread> 
m_weakThread = thread; 
Worker *worker = new Worker; 
//! type of m_weakWorker is QWeakPointer<Worker> 
m_weakWorker = worker; 
worker->moveToThread(thread); 
connect(worker, SIGNAL(error(QString)), this, SLOT(errorString(QString))); 
connect(thread, SIGNAL(started()), worker, SLOT(process())); 
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater())); 
//! instead of finished() signal, connect destroyed() signal to thread's quit() slot 
connect(worker, SIGNAL(destroyed()), thread, SLOT(quit())); 
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); 
thread->start(); 

//! put the following code in destructor 
if (!m_weakThread.isNull()) { 
    QThread *thread = m_weakThread.data(); 
    if (thread->isRunning()) { 
     thread->quit(); 
     thread->wait(); 
    } 
} 
if (!m_weakWorker.isNull()) { 
    Worker *worker = m_weakWorker.data(); 
    m_weakWorker.clear(); //! optional, a little optimization 
    //! it's safe to release worker since the secondary thread exits 
    delete worker; 
} 
if (!m_weakThread.isNull()) { 
    QThread *thread = m_weakThread.data(); 
    m_weakThread.clear(); 
    //! it's safe to release thread since it exits and all objects in it has released 
    delete thread; 
} 
+0

आप बनाई गई वस्तु सूत्र में कार्यकर्ता को नष्ट नहीं कर सकते हैं: और उन्हें run रिटर्न

स्रोत के बाद निष्पादित। चूंकि इसे moveToThread का उपयोग करके थ्रेड में पहले से ही स्थानांतरित कर दिया गया है। क्या आप इसे समझा सकते हैं। – Srikan

+0

इसके अलावा मैं माता-पिता को 'QThread' को असाइन करने की सलाह दूंगा।चूंकि 'क्यू थ्रेड' का उदाहरण थ्रेड का हिस्सा है जहां इसे उत्पन्न किया गया था (किसी ऑब्जेक्ट के विपरीत जो इसे स्थानांतरित किया गया है या इसकी 'रन') विधि है) यह थ्रेड = नया क्यूटीएचड (यह) करने के लिए पूरी तरह से सुरक्षित है; 'अगर' थ्रेड 'किसी अन्य वर्ग का हिस्सा होना है। सामान्य रूप से यदि कोई बेहतर गैर-मैन्युअल समाधान होता है तो आपको 'हटाएं' को कॉल करने से बचना चाहिए। यहां तक ​​कि मानक सी ++ में आपके पास स्मार्ट पॉइंटर्स हैं और जो आपके कंधों से मैन्युअल रूप से सफाई करने का बोझ नहीं लेता है। – rbaleksandar