2011-08-01 7 views
7

संपादित करें:QObject: एक माता पिता के एक अलग सूत्र में है कि के लिए बच्चों बनाया नहीं जा सकता

मैं कर क्या तुम लोग मुझे टिप्पणी में कहा था की कोशिश की ...:

Citizen * c = new Citizen(this); 

QThread thread; 
c->moveToThread(&thread); 

connect(&thread, SIGNAL(started()), c, SLOT(ProcessActions())); 
thread.start(); 

यह और भी पैदा करता है त्रुटियों:

QThread: Destroyed while thread is still running 
ASSERT failure in QThread::setTerminationEnabled(): "Current thread was not started with QThread.", file c:\ndk_buildrepos\qt-desktop\src\corelib\thread\qthread_win.cpp, line 542 
Invalid parameter passed to C runtime function. 
Invalid parameter passed to C runtime function. 
QObject::killTimers: timers cannot be stopped from another thread 

मैं इस त्रुटि के साथ समस्या हो रही हूँ ... मैं पहले से ही 2 दिनों के लिए इस पर अटक कर रहा हूँ और एक समाधान नहीं मिल सकता है।

हैडर:

class Citizen : public QThread 
{ 
Q_OBJECT  
    QNetworkAccessManager * manager; 

private slots: 
    void onReplyFinished(QNetworkReply* net_reply); 

public: 
    Citizen(QObject * parent); 

    void run(); 
}; 

कार्यान्वयन:

Citizen::Citizen(QObject * parent) 
{ 
    manager = new QNetworkAccessManager; 
    connect(_net_acc_mgr, SIGNAL(finished(QNetworkReply*)), 
      this, SLOT(onReplyFinished(QNetworkReply*))); 
} 

void Citizen::onReplyFinished(QNetworkReply* net_reply) 
{ 
    emit onFinished(net_reply); 
} 

void Citizen::run() 
{ 
    manager->get(QNetworkRequest(QUrl("http://google.com")); 

    QEventLoop eLoop; 
    connect(manager, SIGNAL(finished(QNetworkReply *)), &eLoop, SLOT(quit())); 
    eLoop.exec(QEventLoop::ExcludeUserInputEvents); 

    qDebug() << "loaded google!"; 

    exec(); 
} 

जब प्रबंधक> get() निष्पादित हो जाता है, मैं निम्न त्रुटि:

QObject: Cannot create children for a parent that is in a different thread. 
(Parent is QNetworkAccessManager(0xc996cf8), parent's thread is QThread(0xaba48d8), current thread is Citizen(0xca7ae08) 

जब eLoop.exec() ई हो जाता है xecuted:

Citizen * c = new Citizen(this); 
c->start(); 

इस क्यों होता है:

QObject::startTimer: timers cannot be started from another thread 

मैं निम्नलिखित तरीके से इस सूत्र शुरू? इसे कैसे हल करें?

+0

वहाँ इस विषय [धागे, घटनाक्रम और QObjects] के लिए एक अच्छा लेख (है http://qt-project.org/wiki/ Threads_Events_QObjects # 913fb94dd61f1a62fc809f8d842c3afa)। यदि आपका वर्ग नागरिक धागे में काम करता है तो आपको इसे QThread से प्राप्त नहीं करना चाहिए, क्योंकि QThread से विरासत का उद्देश्य धागे में कुछ काम नहीं करना है, लेकिन धागे का प्रबंधन करना है। –

उत्तर

3

मैं सिर्फ तुम क्यों QThread देख रहे हैं जवाब देने की कोशिश करेंगे: नष्ट कर दिया है, जबकि अभी भी धागा त्रुटि चल रहा है।

, तो आप इस

void mtMethod() { 

Citizen * c = new Citizen(this); 
QThread thread; 
c->moveToThread(&thread); 

connect(&thread, SIGNAL(started()), c, SLOT(ProcessActions())); 
thread.start(); 
} 

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

class myClass 
{ 
virtual ~myClass(); 
QThread mythread; 
}; 

myClass::~myClass 
{ 
    mythread.stop(); 
} 

void myClass::mtMethod() { 

    Citizen * c = new Citizen(this); 
    c->moveToThread(&mythread); 

    connect(&mythread, SIGNAL(started()), c, SLOT(ProcessActions())); 
    mythread.start(); 
} 
+1

किसी ऑब्जेक्ट को किसी ऑब्जेक्ट को असाइन करना जिसे बाद में किसी अन्य थ्रेड में ले जाया जाता है, कोई नहीं है। यह जवाब गलत है। @ किम बाउल्स सोहरस का जवाब वह है जिसे इस तरह चिह्नित किया जाना चाहिए। – rbaleksandar

1

मुझे विश्वास नहीं है कि नया धागा चलने तक अस्तित्व में है। तो कन्स्ट्रक्टर रन() से अलग धागा है। क्या होता है यदि आप प्रबंधक ऑब्जेक्ट के निर्माण को कन्स्ट्रक्टर से चलाने के लिए स्थानांतरित करते हैं()? मुझे लगता है कि टाइमर त्रुटि के साथ ही पहली त्रुटि ठीक हो जाएगी।

इसके अलावा, मुझे लगता है कि कई लोग अभी भी आपके जैसे धागे बना रहे हैं, लेकिन आप this को देखना चाहेंगे।

+0

काम नहीं करता है, मैंने उस ब्लॉग पोस्ट को भी चेक आउट किया है। मेरा प्रश्न जांचें – Ahmed

+0

जो काम नहीं किया? प्रबंधक के निर्माण को कन्स्ट्रक्टर से बाहर ले जाना, या लिंक का उपयोग करने के तरीके में moveToThread का उपयोग करना? मुझे नहीं लगता कि आपका संपादन सही है। यदि आप नागरिक को उस वस्तु के रूप में उपयोग करते हैं जो QThread में स्थानांतरित हो जाता है, तो नागरिक QThread से प्राप्त नहीं होना चाहिए। –

+0

पहले, आपके क्यूटीएचड, स्टैक पर बनाए गए, सबराउटिन से बाहर निकलने के बाद नष्ट हो जाते हैं, जो थ्रेड शुरू होता है। आपको यह नहीं चाहिए, मुझे लगता है। आपको QThread को कक्षा के सदस्य बनाना चाहिए। फिर, आपको स्पष्ट रूप से 'छोड़ने' विधि को कॉल करने की आवश्यकता नहीं है। आपका थ्रेड रुक जाएगा जब 'exec' वापसी होगी। – Lol4t0

1

आपको thread affinity पर विचार करने की आवश्यकता है। वह त्रुटि संदेश झूठ बोल रहा है या पागल नहीं है, यह आपको बिल्कुल बता रहा है कि क्या गलत है।

+0

से बाहर ले जाना चाहिए कृपया मेरा प्रश्न फिर से जांचें, मैंने इसे संपादित किया ... – Ahmed

+0

आपका लिंक मर चुका है। – Akiva

1

आपकी समस्याएं ज्यादातर QThread को उपclass करने की कोशिश करने के कारण हैं। भले ही दस्तावेज़ इसे अनुशंसा करता है, यह QThread का उपयोग करने का सबसे अच्छा तरीका नहीं है। अधिक जानकारी और लिंक के लिए कृपया this question and answer देखें।

1

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

हैडर

class Citizen : public QThread { 
    Q_OBJECT 

    QNetworkAccessManager * manager; 

    private slots: 
     void onReplyFinished(QNetworkReply* net_reply); 
    public: 
     Citizen(QObject * parent); 
     void run(); 

    private: 
     void initialize(); 
     void cleanUp(); 
}; 

कार्यान्वयन

Citizen::Citizen(QObject * parent) : 
    manager(NULL) { 
} 

void Citizen::onReplyFinished(QNetworkReply* net_reply) { 
    emit onFinished(net_reply); 
} 

void Citizen::run() { 
    initialize(); 
    manager->get(QNetworkRequest(QUrl("http://google.com")); 

    QEventLoop eLoop; 
    connect(manager, SIGNAL(finished(QNetworkReply *)), 
      &eLoop, SLOT(quit())); 
    eLoop.exec(QEventLoop::ExcludeUserInputEvents); 

    qDebug() << "loaded google!"; 
    exec(); 

    cleanUp(); 
} 

void Citizen::initialize() { 
    manager = new QNetworkAccessManager; 
    connect(_net_acc_mgr, SIGNAL(finished(QNetworkReply*)), 
      this, SLOT(onReplyFinished(QNetworkReply*))); 
} 

void Citizen::cleanUp() { 
    delete manager; 
    disconnect(_net_acc_mgr, SIGNAL(finished(QNetworkReply*)), 
       this, SLOT(onReplyFinished(QNetworkReply*))); 
} 
10
QObject: Cannot create children for a parent that is in a different thread. 

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

यदि आप रन स्लॉट में प्रबंधक बनाते हैं (या नागरिक ऑब्जेक्ट को नए थ्रेड में ले जाने के बाद किसी भी बिंदु पर) ऐसा नहीं होगा।

हालांकि आपको अभी भी कुछ समस्याएं हैं। उदाहरण के लिए, नागरिक वर्ग को वास्तव में QThread होने की आवश्यकता नहीं है। यह अनिवार्य रूप से जटिल है। यह आपके उद्देश्य (afaict) के लिए एक QObject subclass करने के लिए पर्याप्त होगा। बस एक सामान्य स्लॉट बनाएं और इसे QThread :: प्रारंभ() सिग्नल से कनेक्ट करें। और जैसा कि ऑर्कुन ने बताया कि आपको यह सुनिश्चित करने की ज़रूरत है कि QThread उदाहरण ठीक से स्कॉप्ड हो।

सूत्रण के बारे में अधिक के लिए: http://blog.qt.io/blog/2010/06/17/youre-doing-it-wrong/

उदाहरण:

QThread *thread = new QThread; 
thread->start(); 
Citizen *worker = new Citizen; 
worker->moveToThread(thread); 

//startWorking can be equivalent of the run function 
//in your current implementation and this is where you should 
//create the QNetworkAccessManager 
QMetaObject::invokeMethod(worker,"startWorking"); 
संबंधित मुद्दे