【问题标题】:QProcess:execute blocks entire applicationQProcess:execute 阻塞整个应用程序
【发布时间】:2016-09-20 15:39:37
【问题描述】:

在我的应用程序中,我使用以下代码创建新线程并在这些线程中执行外部应用程序:

int main(int argc, char *argv[])
{
...
    WebSocketServer *server = new WebSocketServer();
    QObject::connect(server, &WebSocketServer::closed, &a, &QCoreApplication::quit);
    QObject::connect(server, SIGNAL(messageReceived(QJsonObject)), dm, SIGNAL(sendHandleProcessedFiles(QJsonObject)));
    QObject::connect(dm,SIGNAL(sendServerNotify(int, QByteArray)),server,SLOT( notifySender(int, QByteArray)));
}

void WebSocketServer::processTextMessage(QString message)
{
    QThread* workerThread = new QThread();
    Task *task = Task::createTask(Id);
    task->moveToThread(workerThread);

    QObject::connect(task, SIGNAL(workFinished()), workerThread, SLOT(quit()));
    QObject::connect(workerThread, SIGNAL(finished()), task, SLOT(deleteLater()));
    QObject::connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater()));
    workerThread->start();
    task->execute();
}


void Task::execute()
{
    ...
    //Execute external program 
    QProcess process;
    process->start(cmd);
    process->waitForFinished(-1);
    //Execution should continue after termination of external program within the thread created in WebSocketServer::processTextMessage
    ...
}

在我的任务对象中,我必须执行一个外部程序,等到它的执行完成并继续我的程序代码。我希望我的线程一直等到程序执行终止,所以不需要异步机制。

我遇到的问题是,不仅单个线程等待程序,而且整个应用程序都被阻塞,直到程序终止。所以我收到的所有请求都被阻止了,例如我的 websocket 服务器。

我希望进程在调用它的线程中执行,并且不会影响其他线程。有什么想法吗?

【问题讨论】:

  • 你能提供Task::createTask的实现吗?此外,您没有具体指定调用QProcess::execute 的位置/方式。我怀疑Task::createTask 正在调用QProcess::execute 之前任务被移动到新的QThread。不过只是猜测。
  • 请提供一个完整的最小示例,而不是 sn-ps。您显示的所有代码都是正确的,缺少的位非常重要,因为这就是问题所在。
  • 您很可能是在工作对象的构造函数中启动线程。相反,你应该推迟它直到对象准备好使用 - 即你应该通过使用零持续时间计时器来执行init slot/functor,从事件循环中触发它。
  • 最后,将QProcess 实例移动到不同的线程是没有任何意义的,除非您与进程进行一些繁重的计算/通信。很可能您只是想在流程完成时收到通知:为此,您应该永远使用waitFor 方法;而是连接到finished 信号。您的代码将在该运行时运行。
  • 这个问题很可能与this question 重复。在同一个问题中看到QProcessQThread 通常很难闻。

标签: c++ multithreading qt qthread qprocess


【解决方案1】:

据我了解你的问题,你的问题就在这里:

QThread* workerThread = new QThread();
Task *task = Task::createTask(Id);
task->moveToThread(workerThread);
...
workerThread->start();
task->execute();

在这里,您在主线程中执行任务,而不是在该工作线程中。请注意,moveToThread 所有插槽都在新线程中执行,而不是显式方法调用。

在您的代码中,task->execute(); 在主线程中执行。

【讨论】:

  • 我不知道。如何在我在这里创建的线程中执行它?
  • @HansHupe 一个不错的教程是this page
  • 只需将Task::execute() 设为一个插槽并将其连接到线程的started() 信号
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-30
  • 2013-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多