2010-06-27 21 views
7

मैं एक छोटा बहुप्रचारित वेब सर्वर बना रहा हूं। QTcpSockets को मुख्य थ्रेड में लाया जाता है और फिर QTConcurrent द्वारा QThreadPool तक सौंप दिया जाता है, जो अंततः डेटा को संसाधित करता है और एक उत्तर भेजता है।QThreadPool का उपयोग करते समय QObject :: moveToThread() को कैसे करें?

मेरी समस्या यह है कि सॉकेट मुख्य धागे में बनाया गया है और दूसरे में संसाधित किया गया है। जब सॉकेट से लिखने की कोशिश कर यह त्रुटियों का कारण बनता: ​​

socket->write(somedata); 

QObject: एक माता-पिता के लिए एक अलग थ्रेड में है कि के लिए बच्चों बनाई जा सकती। (पैरेंट QNativeSocketEngine (0x608330), माता पिता की धागा QThread (0x600630 है) है, वर्तमान धागा है QThread (0x505f60)

साफ रास्ता

का उपयोग कर प्रसंस्करण धागा करने के लिए सॉकेट वस्तु ले जाने के लिए होगा
socket->moveToThread(QThread::currentThread()). 

यह, हालांकि, सिर्फ धागा वस्तु में बनाया गया था के भीतर बुलाया जा सकता है। इसके अलावा, सॉकेट, माता पिता के रूप QTcpServer वस्तु है तो moveToThread() वैसे भी (parented वस्तुओं धागे नहीं बदल सकते) असफल हो जायेगी।

मैं ऑब्जेक्ट को थ्रेडपूल द्वारा चलाए गए कोड के भीतर QThread :: currentThread() पर कैसे स्थानांतरित कर सकता हूं? वैकल्पिक रूप से, मैं इसे बनाए गए थ्रेड के बाहर सॉकेट में कैसे लिख सकता हूं?

उत्तर

4

QTcpServer बढ़ाएँ, incomingConnection(int socketDescriptor) reimplement और पूल में धागे के सॉकेट वर्णनकर्ता गुजरती हैं। QRunnable वर्णनकर्ता से QTcpSocket बनाएं और उस सॉकेट के संकेत प्राप्त करने के लिए एक ईवेंट लूप प्रारंभ करें।

0

ब्रैडली ह्यूग्स ने इस विषय के बारे में बात करते हुए क्यूटी लैब्स पर एक पोस्ट लिखा, शायद इससे आपको थोड़ा सा मदद मिलेगी!

http://blog.qt.digia.com/2010/06/17/youre-doing-it-wrong/

+0

धन्यवाद, मुझे यह पोस्ट पता है। असल में मैं इस समय बिल्कुल इस तरह से कर रहा हूं, लेकिन यह थ्रेड पूल के साथ काम नहीं करता है, जिसे मैं उपयोग करना चाहता हूं। जब आप कई धागे में काम वितरित करते हैं तो आप प्रोग्रामिंग में किसी भी तरह के ट्रेड पूल की तरह कुछ भी करते हैं, तो मौजूदा का उपयोग क्यों न करें? :) – grefab

0

मैं यह भी मानता हूं कि incomingConnection(int) को पकड़कर और कार्यकर्ता धागे में सॉकेट बनाना यहां जाने का तरीका है।

लेकिन आपकी समस्या को एक अधिक मौलिक एक था, तो मेरे लिए एक विकल्प है कि आम समस्या (एक धागा पूल में धागे को मनमाने ढंग से QObject रों चलती) को हल करती है को दिखाने के लिए अनुमति देते हैं:

  1. मुख्य थ्रेड में: किसी भी थ्रेड से सॉकेट को अलग करें:

    सॉकेट-> moveToThread (nullptr);

    यह सॉकेट की घटना प्रसंस्करण को निलंबित कर देगा। फिर इसे QtConcurrent को पास करें।

  2. समारोह थ्रेड पूल पर निष्पादित में, आप अब कॉल कर सकते हैं

    socket-> moveToThread (QThread :: currentThread());

    यह ईवेंट प्रसंस्करण को फिर से शुरू करेगा।

किसी भी भाग्य के साथ

, सॉकेट इसके सॉकेट सूचक कार्यकर्ता धागा की घटना पाश के साथ फिर से पुन: पंजीकृत होगा, और आप कार्यकर्ता से कनेक्शन सेवा कर सकते हैं।

दो महत्वपूर्ण चेतावनियां यहाँ है, हालांकि रहे हैं:

  • आप वैश्विक थ्रेड पूल (QThreadPool::globalInstance()) पर कार्य अवरुद्ध नहीं रखना चाहिए। जैसा कि फ़ंक्शन का नाम सुझाता है, वह थ्रेड पूल इंस्टेंस एक वैश्विक संसाधन है, जो QtConcurrent के सभी उपयोगकर्ताओं द्वारा साझा किया जाता है, और सबसे अच्छे मामले में अपने कार्यकर्ता धागे को अवरुद्ध करने से पूल की क्षमता (इस प्रकार, थ्रूपुट) कम हो जाती है और सबसे खराब स्थिति में मृत ताला।
  • यदि आप पहले बिंदु की वजह से QTcpSocket के सिंक्रोनस एपीआई का उपयोग नहीं करने के लिए वर्कर थ्रेड के ईवेंट लूप का उपयोग नहीं करते हैं, तो आपको इसे शुरू करने के लिए QThread::currentThread()->exec() पर कॉल करना होगा। हालांकि, यह एक अवरुद्ध कॉल है और थ्रेड पूल शेड्यूलर के लिए, कर्मचारी व्यस्त दिखेंगे, इसलिए यह इसे और अधिक कार्य नहीं करेगा (यानी QRunnable एस)।

यदि आप वास्तव में एक बहु थ्रेडेड टीसीपी सर्वर को कार्यान्वित करना चाहते हैं, तो आपको अपना खुद का थ्रेड पूल रोल करने की आवश्यकता होगी।

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