खोज…


Qt का उपयोग करना: जब रिसीवर ऑब्जेक्ट सिग्नल प्राप्त नहीं करता है तो डायरेक्टकनेक्टेशन

कुछ बार जब आप देखते हैं कि एक संकेत प्रेषक थ्रेड में उत्सर्जित होता है, लेकिन कनेक्ट किए गए स्लॉट को कॉल नहीं किया जाता है (दूसरे शब्दों में यह सिग्नल प्राप्त नहीं करता है), आपने इसके बारे में पूछा है और अंतिम रूप से पाया गया है कि कनेक्शन प्रकार Qt :: DirectConnection इसे ठीक करेगा, इसलिए समस्या पाई गई और सब कुछ ठीक है।

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

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

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

यहाँ छोटा उदाहरण है जो समस्या को दिखाता है, जैसा कि आप देख सकते हैं नॉनब्लॉकिंगशॉट को कॉल किया जाएगा यहां तक कि ब्लॉकिंग्लॉट को अवरुद्ध इवेंट लूप भी दिया जाएगा जबकि (1) जो खराब कोडिंग को इंगित करता है

class TestReceiver : public QObject{
    Q_OBJECT
public:
    TestReceiver(){
         qDebug() << "TestReceiver Constructed in" << QThread::currentThreadId();
    }
public slots:
    void blockingSlot()
    {
        static bool firstInstance = false;
        qDebug() << "Blocking slot called in thread" << QThread::currentThreadId();
        if(!firstInstance){
            firstInstance = true;
            while(1);
        }
    }
    void nonBlockingSlot(){
        qDebug() << "Non-blocking slot called" << QThread::currentThreadId();
    }
};

class TestSender : public QObject{
    Q_OBJECT
public:
    TestSender(TestReceiver * receiver){
        this->nonBlockingTimer.setInterval(100);
        this->blockingTimer.setInterval(100);

        connect(&this->blockingTimer, &QTimer::timeout, receiver, &TestReceiver::blockingSlot);
        connect(&this->nonBlockingTimer, &QTimer::timeout, receiver, &TestReceiver::nonBlockingSlot, Qt::DirectConnection);
        this->nonBlockingTimer.start();
        this->blockingTimer.start();
    }
private:
    QTimer nonBlockingTimer;
    QTimer blockingTimer;
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    TestReceiver TestReceiverInstance;
    TestSender testSenderInstance(&TestReceiverInstance);
    QThread receiverThread;
    TestReceiverInstance.moveToThread(&receiverThread);
    receiverThread.start();

    return a.exec();
}


Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow