1

我正在使用 Qt(C++)创建一个音乐库应用程序。它涉及一种按给定顺序执行以下工作的方法-

  1. 通过递归遍历一个目录列出N个音频文件。
  2. 阅读每个文件以收集 ID3 标签。
  3. 从文件中提取艺术品图像。
  4. 将 ID3 标签保存在数据库中。

上述任务集非常耗费资源。对于N ~ 1000,完成任务大约需要一分半钟,并且在执行此序列的过程中,GUI 冻结并且响应不佳,因为我目前没有使用其他线程。

我已经看到了一些 Qt 线程的示例,它们或多或少地告诉了如何按预期并行执行操作,但在这些示例中,实现并行性或并发性是一项要求,因为它们没有任何其他选择。但是对于我的应用程序,是否使用多个线程是一个选择。目标是确保 GUI 在执行资源密集型任务期间保持响应性和交互性。我非常感谢任何专家的建议,可能是 Qt 中的代码模板或示例,以在不同的线程中执行资源密集型任务。

主线程中的代码-

QStringList files;
QString status;
createLibrary(files, status);            //To be done in a different thread

if(status == "complete"){
    //do something
}

非常感谢您的时间!

4

2 回答 2

2

您可以使用 QtConcurrent 模块。

使用QtConcurrent::map()遍历文件列表并在单独的线程中调用方法:

QFuture<void> result = QtConcurrent::map(files, createLibrary);

QFutureWatcher将在处理完成时发送一个信号:

QFutureWatcher<void> watcher;
connect(&watcher, SIGNAL(finished()), 
        this, SLOT(processingFinished()));

// Start the computation.
QFuture<void> result = QtConcurrent::map(files, createLibrary);
watcher.setFuture(result);

顺便说一句,由于存在大量不良文件,音乐播放器 Amarok 决定将 id3 标签扫描器放在一个单独的进程中。请参阅此处了解更多信息。

于 2013-07-04T12:58:56.507 回答
1

我最好的建议是创建一个 subclass QThread。向这个子类传递一个指向目录的指针,并给它一个指向您想要通过以下方式更新的有效(非空)视图的指针:

头文件.h

class SearchAndUpdate : public QThread
{
    Q_OBJECT
public:
    SearchAndUpdate(QStringList *files, QWidget *widget);
    //The QWidget can be replaced with a Layout or a MainWindow or whatever portion
    //of your GUI that is updated by the thread.  It's not a real awesome move to
    //update your GUI from a background thread, so connect to the QThread::finished()
    //signal to perform your updates.  I just put it in because it can be done.
    ~SearchAndUpdate();
    QMutex mutex;
    QStringList *f;
    QWidget *w;
    bool running;
private:
    virtual void run();
};

然后在该线程的实现中执行以下操作:

线程.cpp

SearchAndUpdate(QStringList *files, QWidget *widget){
     this->f=files;
     this->w=widget;
}

void SearchAndUpdate::run(){
    this->running=true;
    mutex.lock();

    //here is where you do all the work
    //create a massive QStringList iterator
    //whatever you need to complete your 4 steps.
    //you can even try to update your QWidget *w pointer
    //although some window managers will yell at you

    mutex.unlock();
    this->running=false;
    this->deleteLater();
}

然后在您的 GUI 线程中维护有效的指针QStringList *filesSearchAndUpdate *search,然后执行以下操作:

files = new QStringList();
files->append("path/to/file1");
...
files->append("path/to/fileN");
search = new SearchAndUpdate(files,this->ui->qwidgetToUpdate);
connect(search,SIGNAL(finished()),this,SLOT(threadFinished()));
search->start();

...

void threadFinished(){
    //update the GUI here and no one will be mad
}
于 2013-07-04T13:48:08.053 回答