2013-10-03 5 views
5

मैं एक ऐप लिख रहा हूं जो क्यूटी का उपयोग करके एक साथ चल रहे कई libVlc उदाहरण एम्बेड करता है। ऐसा लगता है कि वीएलसी लाइब्रेरी में एक बग है जहां कभी-कभी libvlc_media_player_stop deadlocks को क्यूटी के जीयूआई थ्रेड से बुलाया जाता है। वीडियोलन मंचों में से एक पर, स्वीकृत समाधान स्टॉप फ़ंक्शन को किसी अन्य थ्रेड से कॉल करना था। मैं एक अलग धागे से रोकने के लिए कम से कम शामिल और बहुत ही बदसूरत विधि की तलाश में हूं। मैंने QThreadPool का उपयोग करने पर ध्यान दिया जो वास्तव में इस तरह की परिस्थितियों के लिए है, लेकिन मेरे विशेष मामले में, यह समाधान को सुंदर नहीं बनाता है।लिनक्स पर सी ++/क्यूटी में धागे को आग और भूलने का सबसे आसान तरीका क्या है?

यहाँ मेरी कोड का एक टुकड़ा है:

VlcWidget.h

class VlcWidget : public QWidget 
    { 
     Q_OBJECT 

    private: 

     // State 
     bool _isPlaying; 

     // The streaming source, title and quality data 
     VideoData _videoData; 
     VIDEO_QUALITY _quality; 

     // LibVlc related members 
     libvlc_instance_t *_vlcInstance; 
     libvlc_media_player_t *_vlcMediaPlayer; 
     libvlc_media_t *_vlcMedia; 
     int _vlcTrackID; 
    } 

VlcWidget.c

void VlcWidget::Play() 
    { 
     if(_videoData.Source() != "" && !_isPlaying) 
     { 
      // Create a new media descriptor 
      _vlcMedia = libvlc_media_new_location(
          _vlcInstance, 
          _videoData.Source().toStdString().c_str()); 

      // Tell the user about incorrect URL 
      if(_vlcMedia == NULL) 
      { 
       QMessageBox::information(this, 
             _videoData.Title(), 
             "Unable to open source Url.\nPlease check the source and try again."); 
       return; 
      } 

      libvlc_media_player_set_media(_vlcMediaPlayer, _vlcMedia); 
      libvlc_media_release(_vlcMedia); 
      libvlc_media_player_set_xwindow(_vlcMediaPlayer, parentWidget()->winId()); 
      libvlc_media_player_play(_vlcMediaPlayer); 
      _vlcTrackID = libvlc_audio_get_track(_vlcMediaPlayer); 
      _isPlaying = true; 
     } 
    } 

    void VlcWidget::Stop() 
    { 
     if(_isPlaying) 
     { 
      libvlc_media_player_stop(_vlcMediaPlayer); 
      _vlcTrackID = -1; 
      _isPlaying = false; 
     } 
    } 

QthreadPool का उपयोग कर मेरे समाधान की तरह देखा:

class AsyncVlcPlay : public QRunnable 
    { 
    private: 
     // State 
     bool *_isPlaying; 

     // LibVlc related members 
     libvlc_instance_t *_vlcInstance; 
     libvlc_media_player_t *_vlcMediaPlayer; 
     libvlc_media_t *_vlcMedia; 
     int *_vlcTrackID; 

    public: 
     virtual void run(); 
    } 

और AsyncVlcPl ay :: run() वास्तव में क्या करता है VlcWidget :: Play() इसमें सरल लॉकिंग के साथ जोड़ा जाता है। और मुझे VlcWidget :: Stop() के लिए एक समान कक्षा की भी आवश्यकता होगी। मुझे इस समाधान को पसंद नहीं है क्योंकि मुझे जो हासिल करने की कोशिश कर रहा हूं उसके लिए मुझे वास्तव में 2 नए वर्गों की आवश्यकता नहीं है। और उससे भी बदतर यह तथ्य है कि मुझे VlcWidgets निजी सदस्यों को किसी अन्य वर्ग के ऑब्जेक्ट में पास करना होगा। मुझे पूरा यकीन है कि एक बेहद सरल तरीका है कि मुझे पता नहीं है और उम्मीद है कि आप में से कोई भी मेरी मदद कर सकता है। धन्यवाद!

(वास्तव में, मैं वास्तव में VlcWidget :: प्ले() की आवश्यकता नहीं है एक और धागा पर हो सकता है, लेकिन मैं प्ले और स्टॉप सममित रखना चाहते हैं)

+0

हो सकता है कि [QtConcurrent] (http है : //qt-project.org/doc/qt-4.8/qtconcurrentrun.html) वह है जिसे आप ढूंढ रहे हैं। – thuga

+0

@ थुगा - बहुत बहुत धन्यवाद!यही वही है जो मैं देख रहा था :) – Kulki

+0

यदि आप QtConcurrent का उपयोग करने जा रहे हैं, तो मेरा सुझाव है कि आप इसे पहले पढ़ लें: http://comments.gmane.org/gmane.comp.lib.qt.devel/7942 – TheDarkKnight

उत्तर

0

यहाँ मेरी (का हिस्सा) SWI-Prolog वाक्य रचना क्यूटी

// start highlighting, using SWI-Prolog syntax analyzer to collect structured data 
// 
void pqSource::startHighliter() { 
    auto f = [](QString file, pqSyntaxData* psd) { 
     SwiPrologEngine::in_thread _it; 
     try { 
      // ?? PlCall("consult", V(A(file))); 
      qDebug() << "running syntax color on" << file << "thread" << CT; 
      int rc = PlCall("syncol", PlTermv(A(file), PlTerm(psd))); 
      qDebug() << "syncol" << rc; 
     } 
     catch(PlException e) { 
      qDebug() << t2w(e); 
     } 
    }; 

    // collect structure asyncronously 
    auto w = new QFutureWatcher<void>; 
    connect(w, SIGNAL(finished()), this, SLOT(runHighliter())); 

    // since could be a slow task, place a visual hint to what's going on... 
    CenterWidgets((sd = new pqSyntaxData)->pgb = new QProgressBar(this)); 
    QTextCursor c = textCursor(); 
    c.movePosition(c.End); 
    sd->pgb->setMaximum(c.position()); 
    connect(sd, SIGNAL(onProgress(int)), sd->pgb, SLOT(setValue(int))); 
    sd->pgb->show(); 

    // run the Prolog snippet in background (hl pointer) 
    w->setFuture(QtConcurrent::run(f, file, sd)); 
} 

मुझे लगता है कि आप लैम्ब्डा के उपयोग में रुचि रखने वाले को उजागर करने के लिए युग्मन कोड ...

1

मैं QThread के साथ इस समस्या से निपटने होगा। इसका नाम वास्तव में भ्रामक है क्योंकि यह वास्तव में एक धागा नहीं है, लेकिन एक धागा नियंत्रक और उपयोग करने में बहुत आसान है।

क्यूओब्जेक्ट से विरासत में प्राप्त किसी भी वर्ग को धागे में ले जाया जा सकता है और धागे के बीच संचार सिग्नल/स्लॉट तंत्र के साथ किया जा सकता है। इसलिए, आप ऐसा कुछ कर सकते हैं: -

class VlcObject : public QObject 
{ 
    Q_OBJECT 

    public slots: 
     void Run(); 

    private slots; 
     void StopVlc(); 
}; 

इस कक्षा में सभी वीएलसी ऑब्जेक्ट्स/उदाहरण शामिल हो सकते हैं। इसके बाद आप एक धागा नियंत्रक वस्तु बनाने और नए सूत्र को VlcObject उदाहरण के लिए कदम: -

QThread* pThread = new QThread(this); // where this is a parent, running on the main thread 
VlcObject* pVlcObj = new VlcObject; 

pVlcObj->moveToThread(pThread); 

// Note, this is Qt 5 connect style - Qt 4 connections also work 
connect(pThread, &QThread::started, pVlcOj, &VlcObject::Run(); 

// Start the thread running 
pThread->start(); 

QVlcWidget मान लिया जाये कि एक बटन pStopVlc कहा जाता है के साथ एक जीयूआई वर्ग है, तो आप अन्य धागे के VlcObject पर रोक फोन बटन जोड़ने के द्वारा VlcObject के StopVlc कार्य करने के लिए: -:

connect(pThread, &QThread::finished, pThread, &Qthread::deleteLater); 
-

connect(pStopVlc, &QPushButton::released, pVlcObj, &VlcObject::StopVlc); 

वैकल्पिक रूप से, आप कर सकता है StopVlc जब धागा इस्तीफा और जब यह बंद हो जाता है QThread खुद को साफ करने के लिए यह संभव है कहा जाता है

+1

मुझे उस हिस्से से प्यार है जहां आप ढेर पर धागा बनाते हैं और हटाए गए लेटर स्लॉट से कनेक्ट करने के बाद इसके बारे में भूल जाते हैं! मुझे नहीं पता था कि आप ऐसा कर सकते हैं (मैं अभी तक क्यूटी में केवल एक सप्ताह पुराना हूं)। – Kulki

+0

और करता है -> moveToThread का अर्थ है कि भविष्य में pvlcObj जो कुछ भी करता है वह नए धागे पर होगा? शायद वह नहीं है जो मैं चाहता हूं। – Kulki

+0

@ कुल्की आप पीवीएलसीओबीजे को सिग्नल जोड़ सकते हैं और उन्हें अन्य थ्रेड –

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