Qt: सही ढंग से धाराओं के साथ काम करने के लिए टेम्पलेट - बेहतर कार्यान्वयन

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

अब हम qhhread को आधार के रूप में लेंगे और उससे एक टेम्पलेट वारिस बनाएंगे ( Schlee पुनर्वासित!)। दृष्टिकोण इस प्रकार होगा:
  1. एक क्यूथ्रेड धागा बनाना;
  2. इसमें , वर्तमान थ्रेड में एक नई स्ट्रीम की जानकारी तैयार की जाती है ;
  3. ग्राहक कॉल शुरू (प्राथमिकता) ...
  4. ... और ओवरराइड रन () विधि में - एक नए धागे में - वांछित वस्तु बनाई गई है, संचार स्थापित किए जाते हैं, संकेत "ऑब्जेक्ट तैयार है" कहा जाता है और संदेश प्रसंस्करण चक्र शुरू होता है;
  5. स्रोत स्ट्रीम में क्लाइंट सिग्नल और एक नई वस्तु प्राप्त करता है।

पिछली बार की तरह, याद रखें कि MOC टेम्पलेट क्लास को संसाधित नहीं कर सकता है : “MOC C ++ की सभी विशेषताओं का उपयोग करने की अनुमति नहीं देता है। मुख्य समस्या यह है कि क्लास टेम्प्लेट में सिग्नल या स्लॉट नहीं हो सकते हैं । "

कार्यान्वयन


बनाई गई कक्षाओं के कोड पर विचार करें (ताकि यह सब स्क्रीन में फिट हो जाए, मैंने टिप्पणियाँ हटा दीं):

// ** // **     // ** class ThreadedObjectBase: public QThread { Q_OBJECT protected: const char *_finished_signal; const char *_terminate_slot; bool _to_delete_later_object; void initObject (QObject *obj) { bool res; if (_finished_signal) { res = connect (obj, _finished_signal, this, SLOT (quit ())); Q_ASSERT_X (res, "connect", "connection is not established"); } if (_terminate_slot) { res = connect (this, SIGNAL (finished ()), obj, _terminate_slot); Q_ASSERT_X (res, "connect", "connection is not established"); } if (_to_delete_later_object && _finished_signal) { res = connect (obj, _finished_signal, obj, SLOT (deleteLater ())); Q_ASSERT_X (res, "connect", "connection is not established"); } emit objectIsReady (); } public: ThreadedObjectBase (QObject *parent = 0): QThread (parent), _finished_signal (0), _terminate_slot (0), _to_delete_later_object (true) {} signals: void objectIsReady (void); }; // ** // **     // ** template <class T> class ThreadedObject: public ThreadedObjectBase { protected: T *_obj; public: ThreadedObject (QObject *parent = 0): ThreadedObjectBase (parent), _obj (0) {} void starting ( const char *FinishedSignal = 0, const char *TerminateSlot = 0, QThread::Priority Priority = QThread::InheritPriority, bool ToDeleteLaterThread = true, bool ToDeleteLaterObject = true) { _finished_signal = FinishedSignal; _terminate_slot = TerminateSlot; _to_delete_later_object = ToDeleteLaterObject; start (Priority); } void run (void) { initObject (_obj = new T); exec (); } bool objectIsCreated (void) const { return _obj != 0; } T* ptr (void) { return reinterpret_cast <T*> (_obj); } const T* cptr (void) const { return reinterpret_cast <const T*> (_obj); } operator T* (void) { return ptr (); } T* operator -> (void) { return ptr (); } operator const T* (void) const { return cptr (); } const T* operator -> (void) const { return cptr (); } }; 


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

इन वर्गों का उपयोग करने का एक सरल उदाहरण यहां दिया गया है:

 ThreadedObject <Operation> _obj; QObject::connect (&_obj, SIGNAL (objectIsReady ()), this, SLOT (connectObject ())); _obj.starting (SIGNAL (finished ()), SLOT (terminate ()), QThread::HighPriority); 


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

उदाहरण + कक्षाएं
थ्रेडऑबजेक्ट फ़ाइल:

 #include <QtCore> // ** // **     // ** class ThreadedObjectBase: public QThread { Q_OBJECT protected: const char *_finished_signal; //   "  " const char *_terminate_slot; //   " " bool _to_delete_later_object; //     // .  void initObject (QObject *obj) { bool res; if (_finished_signal) //   "  "? { res = connect (obj, _finished_signal, this, SLOT (quit ())); Q_ASSERT_X (res, "connect", "connection is not established"); } //        if (_terminate_slot) //   " "? { res = connect (this, SIGNAL (finished ()), obj, _terminate_slot); Q_ASSERT_X (res, "connect", "connection is not established"); } //        " " if (_to_delete_later_object && _finished_signal) //    ? { res = connect (obj, _finished_signal, obj, SLOT (deleteLater ())); Q_ASSERT_X (res, "connect", "connection is not established"); } //         emit objectIsReady (); //     } public: ThreadedObjectBase (QObject *parent = 0): QThread (parent){} signals: void objectIsReady (void); //  " " }; // class ThreadedObject // ** // **     // ** template <class T> class ThreadedObject: public ThreadedObjectBase { protected: T *_obj; // ,     public: ThreadedObject (QObject *parent = 0): ThreadedObjectBase (parent), _obj (0) {} // .  void starting (const char *FinishedSignal = 0, const char *TerminateSlot = 0, QThread::Priority Priority = QThread::InheritPriority, bool ToDeleteLaterThread = true, bool ToDeleteLaterObject = true) //    { _finished_signal = FinishedSignal; //    "  " _terminate_slot = TerminateSlot; //    " " _to_delete_later_object = ToDeleteLaterObject; //      start (Priority); //   } void run (void) { initObject (_obj = new T); exec (); } //   // .  bool objectIsCreated (void) const { return _obj != 0; } //    ? T* ptr (void) { return reinterpret_cast <T*> (_obj); } //    const T* cptr (void) const { return reinterpret_cast <const T*> (_obj); } //     // .  operator T* (void) { return ptr (); } //    T* operator -> (void) { return ptr (); } //    operator const T* (void) const { return cptr (); } //     const T* operator -> (void) const { return cptr (); } //     }; // class ThreadedObject 


Main.cpp फ़ाइल:

 #include <QtGui> #include <QtWidgets> #include <QtCore> #include "ThreadedObject.h" // ** // **   // ** class Operation: public QObject { Q_OBJECT int *Int; //    QTimer _tmr; //  int _int_timer; //   public: Operation (void) { Int = new int (5); } //   ~Operation (void) { if (Int) delete Int; } //   signals: void addText(const QString &txt); //  " " void finished (); //  " " public slots: void terminate () //   { killTimer (_int_timer); //    _tmr.stop (); //    delete Int; //   Int = 0; //    emit finished (); //    } void doAction (void) //   { bool res; emit addText (QString ("- %1 -"). arg (*Int)); res = QObject::connect (&_tmr, &QTimer::timeout, this, &Operation::timeout); Q_ASSERT_X (res, "connect", "connection is not established"); //    _tmr.start (2000); //    thread()->sleep (1); //  1 ... timeout (); // ...   ... startTimer (2000); // ...     } protected: void timerEvent (QTimerEvent *ev) { timeout (); } //   private slots: void timeout (void) { if (!Int || !*Int) //  ? return; // ...  --*Int; //   emit addText (QString ("- %1 -"). arg (*Int)); //   if (!Int || !*Int) //  ? emit finished (); // ...  } }; // ** // ** ,    // ** class App: public QObject { Q_OBJECT ThreadedObject <Operation> _obj; // - QPushButton _btn; //  protected: void timerEvent (QTimerEvent *ev) { bool res; //    - killTimer (ev->timerId ()); //   res = QObject::connect (&_obj, SIGNAL (objectIsReady ()), this, SLOT (connectObject ())); Q_ASSERT_X (res, "connect", "connection is not established"); //     _obj.starting (SIGNAL (finished ()), SLOT (terminate ()), QThread::HighPriority); //      } private slots: void setText (const QString &txt) { _btn.setText (txt); } //     void connectObject (void) //     { bool res; //    - res = QObject::connect (this, &App::finish, _obj, &Operation::terminate); Q_ASSERT_X (res, "connect", "connection is not established"); //        res = QObject::connect (this, &App::startAction, _obj, &Operation::doAction); Q_ASSERT_X (res, "connect", "connection is not established"); //     res = QObject::connect (_obj, &Operation::finished, this, &App::finish); Q_ASSERT_X (res, "connect", "connection is not established"); //      res = QObject::connect (_obj, &Operation::addText, this, &App::setText); Q_ASSERT_X (res, "connect", "connection is not established"); //     res = QObject::connect (&_btn, &QPushButton::clicked, _obj, &Operation::terminate); Q_ASSERT_X (res, "connect", "connection is not established"); //    _btn.show (); //   emit startAction (); //   } public slots: void terminate (void) { emit finish (); } //    signals: void startAction (void); //  " " void finish (void); //  " " }; // ** // **     // ** int main (int argc, char **argv) { QApplication app (argc, argv); //  App a; //  bool res; //    a.startTimer (0); //          res = QObject::connect (&a, SIGNAL (finish ()), &app, SLOT (quit ())); Q_ASSERT_X (res, "connect", "connection is not established"); //      res = QObject::connect (&app, SIGNAL (lastWindowClosed ()), &a, SLOT (terminate ())); Q_ASSERT_X (res, "connect", "connection is not established"); //      return app.exec(); //     } #include "main.moc" 

Source: https://habr.com/ru/post/In203254/


All Articles