2012-02-20 22 views
5

छोड़कर मैं धागे के साथ संयोजन में क्यूटी संकेतों और स्लॉट की बेहतर समझ खोजने की कोशिश कर रहा हूं।क्यूटी थ्रेड बाहर निकलने के बाद रुकता नहीं है/

foo.h:

#include <QObject> 

class A : public QObject { 
    Q_OBJECT 

public: 
    void doit(); 

signals: 
    void x(); 
}; 

class B : public QObject { 
    Q_OBJECT 

public slots: 
    void h(); 
}; 

foo.cpp:

#include "foo.h" 

#include <QThread> 
#include <QCoreApplication> 

void B::h() { 
    qDebug("[%d] B::h() here!", (int) QThread::currentThreadId()); 
    QCoreApplication::instance()->quit(); 
} 

void A::doit() { 
    qDebug("[%d] emitting...", (int) QThread::currentThreadId()); 
    emit x(); 
} 

int main(int argc, char* argv[]) { 
    QCoreApplication app(argc, argv); 
    A a; 
    B b; 
    QObject::connect(&a, SIGNAL(x()), &b, SLOT(h())); 
    QThread t; 
    t.start(); 
    b.moveToThread(&t); 
    a.doit(); 
    t.wait(); 
    return 0; 
} 

सब कुछ ठीक है, केवल t.wait() अंत में कभी नहीं देता है तो मैं इस कम से कम आवेदन की कोशिश की। मेरी समझ छोड़ना है() को ईवेंट लूप को रोकना चाहिए, जिसका अर्थ है कि exec() को वापस जाना चाहिए और इसलिए चलाना चाहिए() और थ्रेड निष्पादन रोकना चाहिए। क्या मैं कुछ भूल रहा हूँ?

+3

आपके तरीकों का नाम उनके उद्देश्य को स्पष्ट करना चाहिए। – UmNyobe

+0

चिंता न करें, यह उत्पादन कोड नहीं है! मुझे कृत्रिम रूप से वर्णनात्मक नामों की तुलना में छोटे नमूना/परीक्षण कोड में नकली नाम बहुत बेहतर काम करते हैं। – Elektito

+0

मैं UmNyobe से सहमत हूं। यदि आपने अधिक जानकारीपूर्ण नामों का उपयोग किया है तो नमूना कोड को पढ़ना और समझना आसान होगा। जैसे ए :: doit() -> ए :: emitThreadStart(), शून्य x() -> startThread(), शून्य एच() -> शून्य छोड़ दें आवेदन() ... आदि – Dmitriy

उत्तर

10

QCoreApplication::quit() थ्रेड-सुरक्षित विधि के रूप में नहीं कहा गया है, इसलिए आप इसे किसी अन्य थ्रेड से नहीं बुला सकते हैं। आपका एप्लिकेशन क्रैश या अपरिभाषित व्यवहार (यूबी) प्राप्त कर सकता है।

t.wait() कभी वापस नहीं आएगा क्योंकि चलने वाला धागा लगातार घटनाओं की प्रतीक्षा कर रहा है। धागा बंद करने के लिए आप कॉल करना होगा QThread::quit() [slot]

आप अनुप्रयोग से बाहर करना चाहते हैं के बाद काम आप एक संकेत है, जो QCoreApplication::quit() [static slot]

से जुड़ा है फेंकना करने के लिए है कि आप के बाद कार्यकर्ता धागा बंद करना चाहते हैं किया जाता है आगे

महत्वपूर्ण नोटिस पढ़ने के लिए Threads, Events and QObjects: काम आप भी एक संकेत फेंकना, किया जाता है की है, void QThread::quit() [slot]

जोड़ा जुड़े आप कॉल करना होगा QCoreApplication::exec() मैं n आदेश & धागे, कतारबद्ध कनेक्शन के बीच स्लॉट तंत्र का उपयोग करने में सक्षम होने के लिए आदेश।

क्यूटी QThread डॉक से:

प्रत्येक QThread अपनी ही घटना पाश हो सकता है। आप exec() को कॉल करके इवेंट लूप प्रारंभ कर सकते हैं; आप इसे बाहर निकलें() या छोड़कर() छोड़कर रोक सकते हैं। होने पर एक थ्रेड में एक ईवेंट लूप से अन्य धागे को कतार कनेक्शन नामक एक तंत्र का उपयोग करके इस थ्रेड में स्लॉट पर सिग्नल कनेक्ट करना संभव बनाता है। यह उन वर्गों का उपयोग करना भी संभव बनाता है जिनके लिए थ्रेड में ईवेंट लूप, जैसे QTimer और QTcpSocket की आवश्यकता होती है। नोट, हालांकि, धागे में किसी भी विजेट कक्षाओं का उपयोग करना संभव नहीं है।

क्यूटी :: QueuedConnection के लिए डॉक्टर:

स्लॉट शुरू हो जाती है जब रिसीवर के धागे की घटना पाश करने के लिए नियंत्रण रिटर्न। स्लॉट रिसीवर के धागे में निष्पादित किया जाता है।

+0

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

+0

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

+0

आपके कोड स्निपेट में, आपके अतिरिक्त नोटिस के बारे में, मैंने 'QCoreAplication :: exec()' नहीं कहा है लेकिन सिग्नल/स्लॉट काम करते हैं। मुझे लगता है कि QThread के अंदर घटना लूप पर्याप्त है। – Elektito

2

ऐसा लगता है कि आपके कोड के साथ कई चीज़ें गलत हैं।

  • आप app.exec() पर कॉल नहीं करते हैं। मतलब है कि कोई मुख्य घटना लूप नहीं है। xA का संकेत उत्सर्जित नहीं किया जाएगा।
  • डिफ़ॉल्ट रूप से, क्यूटी में has it's own even loop धागा (कम से कम कुछ वर्षों से)। फिर एक थ्रेड कॉल Qthread::run() शुरू करें, और ईवेंट लूप प्रारंभ हो गया है। यही वह जगह है जहां आपका धागा t.wait() में नहीं है।
  • t.wait() का उद्देश्य क्या है? मेरा मानना ​​है कि आप इसका दुरुपयोग कर रहे हैं।
  • (यदि सबकुछ ठीक था), B::h() में आप अन्य धागे से मुख्य धागे को रोक रहे हैं। क्या आप यही करना चाहते हैं?

तो मेरी पहली सलाह app.exec() जोड़ने के लिए होगी, देखें कि यह कैसा व्यवहार करता है। समझाओ कि आप क्या करने की कोशिश कर रहे हैं, और कुछ और लिखो। क्योंकि you're doing it wrong

+0

t.start() रन() विधि को कॉल करता है जिसका डिफ़ॉल्ट कार्यान्वयन exec() को कॉल करता है। जैसा कि मैंने कहा, संकेत _are_ उत्सर्जित और सही ढंग से प्राप्त किया। प्रतीक्षा करें() pthread_join के बराबर है, या तो दस्तावेज कहता है, इसलिए मैं थ्रेड को समाप्त करने के लिए इंतजार कर रहा हूं। अंत में, आपका अंतिम बिंदु सही है। मैं थ्रेड इवेंट लूप को रोक नहीं रहा हूं। उस पंक्ति को 'QThread :: currentThread() -> छोड़ें()' में बदलना चाल है। धन्यवाद। – Elektito

+0

exec() चल रहा रहता है इसलिए प्रतीक्षा करें() का कोई प्रभाव नहीं है। – UmNyobe

+0

यह निश्चित रूप से सच है, लेकिन प्रतीक्षा() का इरादा exec() के अंत की प्रतीक्षा करना है, इसलिए प्रतीक्षा() का उपयोग गलत नहीं है; सही घटना लूप को रोक नहीं है। App.exec() के लिए – Elektito

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