什么是在linux上c / Qt中解雇和忘记线程的最简单方法?

我正在编写一个嵌入多个使用Qt同时运行的libVlc实例的应用程序. vlc库中似乎存在一个错误,如果从Qt的GUI线程调用,有时libvlc_media_player_stop会死锁.在其中一个videolan论坛上,接受的解决方案是从另一个线程调用stop函数.我正在寻找最少参与且不太难看的方法来从不同的线程调用stop.我看着使用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();
    }

并且AsyncVlcPlay :: run()与VlcWidget :: Play()完全相同,并添加了简单锁定.而且我还需要一个类似VlcWidget :: Stop()的类.我不喜欢这个解决方案,因为我不应该为我想要实现的目标真正需要2个新类.更糟糕的是,我必须将VlcWidgets私有成员传递给另一个类的对象.我很确定这是一种非常简单的方式,我不知道,并希望你们中的一个人可以帮助我.谢谢!

(事实上​​,我真的不需要VlcWidget :: Play()在另一个线程上,但我想保持Play和Stop对称)

解决方法

这是我的(部分)代码,用于将SWI-Prolog语法高亮显示耦合到Qt

// 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));
}

我想你可能对lambda的使用感兴趣…

相关文章

linux常用进程通信方式包括管道(pipe)、有名管道(FIFO)、...
Linux性能观测工具按类别可分为系统级别和进程级别,系统级别...
本文详细介绍了curl命令基础和高级用法,包括跳过https的证书...
本文包含作者工作中常用到的一些命令,用于诊断网络、磁盘占满...
linux的平均负载表示运行态和就绪态及不可中断状态(正在io)的...
CPU上下文频繁切换会导致系统性能下降,切换分为进程切换、线...