C++ 终止在其他QThread中运行的QProcess

C++ 终止在其他QThread中运行的QProcess,c++,multithreading,qt,qthread,qprocess,C++,Multithreading,Qt,Qthread,Qprocess,我有一个继承QThread的类,我重新实现了run()方法。在这个run方法中,有一个启动程序的QProcess(在run中声明) 现在,如果在进程仍在运行时关闭应用程序,它实际上将在进程完成之前不会关闭 所以我的问题是如何停止这个过程 从我在Qt文档中读到的内容来看,我不能在这里使用signal/slot,因为我的进程将与非主线程的线程具有线程关联性,因此连接是排队的,这不会停止我的进程 我正在使用Qt5.8 提前谢谢 编辑:这是线程代码,如果您需要更多,请告诉我 void run() {

我有一个继承
QThread
的类,我重新实现了
run()
方法。在这个run方法中,有一个启动程序的
QProcess
(在run中声明)

现在,如果在进程仍在运行时关闭应用程序,它实际上将在进程完成之前不会关闭

所以我的问题是如何停止这个过程

从我在Qt文档中读到的内容来看,我不能在这里使用signal/slot,因为我的进程将与非主线程的线程具有线程关联性,因此连接是排队的,这不会停止我的进程

我正在使用Qt5.8

提前谢谢

编辑:这是线程代码,如果您需要更多,请告诉我

void run()
{
    QString cmd;
    QProcess p;

    connect(&p, SIGNAL(finished(int)), this, SLOT(quit()));
    //connect(this, SIGNAL(signalTerminateProcess()), &p, SLOT(kill())); // queued connect that doesn't kill my process

    p.start(cmd);
    if(p.waitForFinished(-1))
    {
        qInfo("process done");
    }
}

首先,您可以跨QThreads使用signal&slot,甚至可以使用
Qt::BlockingQueuedConnection
等待执行插槽。看

但是,这要求目标QObject位于具有运行事件循环的线程中。在您的情况下,由于您重载了
QThread::run()
,因此不会有事件循环

在我看来,修复代码有两种方法,一种是进行小的修复,另一种是更改设计并使用事件循环

1.快速修复 或

2.事件循环修复 你可以:

  • 通过使用原子或使用连接到
    Qt::BlockingQueuedConnection
    的信号替换互斥锁
  • 用插槽和lambda替换
    startProcess()
    stopProcess()
  • QMetaObject::invokeMethod()
    或使用信号替换对
    QTimer::singleShot()
    的调用。请注意,您可以将
    Qt::BlockingQueuedConnection
    QMetaObject::invokeMethod()一起使用

首先,您可以跨Qt线程使用信号和插槽,甚至可以使用
Qt::BlockingQueuedConnection
等待插槽执行。看

但是,这要求目标QObject位于具有运行事件循环的线程中。在您的情况下,由于您重载了
QThread::run()
,因此不会有事件循环

在我看来,修复代码有两种方法,一种是进行小的修复,另一种是更改设计并使用事件循环

1.快速修复 或

2.事件循环修复 你可以:

  • 通过使用原子或使用连接到
    Qt::BlockingQueuedConnection
    的信号替换互斥锁
  • 用插槽和lambda替换
    startProcess()
    stopProcess()
  • QMetaObject::invokeMethod()
    或使用信号替换对
    QTimer::singleShot()
    的调用。请注意,您可以将
    Qt::BlockingQueuedConnection
    QMetaObject::invokeMethod()一起使用

显示线程代码。如果可以简单地使用QProcess信号,为什么要使用线程来执行进程?因为在我的run函数中有两种情况,其中一种无法使用QProcess完成,但我决定将这两个部分都保留在这个QThread类中,您可以尝试使用connect(this,SIGNAL(finished()),&p,SLOT(close())使用显示的代码,如果停止进程,线程将终止。使用QProcess::kill()显示线程代码。如果可以简单地使用QProcess信号,为什么要使用线程来执行进程?因为在我的run函数中有两种情况,其中一种不能用QProcess完成,但我决定将这两个部分都保留在这个QThread类中,您可以尝试使用connect(this,SIGNAL(finished()),&p,SLOT(close())和显示的代码,如果停止进程,线程将终止。使用QProcess::kill()嗨,本杰明,你的第一次修复成功了,真是太棒了!不知怎的,谷歌总是向我展示Qt4.8中的QThread doc页面,而requestInterruption()在那时不是什么东西,所以我错过了它。嗨,本杰明,你第一次修复了,效果很好!不知怎的,谷歌总是向我展示Qt4.8中的QThread doc页面,而requestInterruption()在当时不是什么东西,所以我错过了它。
void run()
{
    QString cmd;
    QProcess p;

    connect(&p, SIGNAL(finished(int)), this, SLOT(quit()));
    //connect(this, SIGNAL(signalTerminateProcess()), &p, SLOT(kill())); // queued connect that doesn't kill my process

    p.start(cmd);
    while(! p.waitForFinished(100)) //Wake up every 100ms and check if we must exit
    {
        if (QThread::currentThread()->isInterruptionRequested())
        {
            p.terminate();
            if (! p.waitForFinished(1000))
                p.kill()
            break;
        }
    }
    qInfo("process done");
}

int cleanUp()
{
    thread->requestInterruption();
    thread->wait();
}
QProcess *process = nullptr;
void run()
{
    QString cmd;
    QProcess p;
    process = &p; //You shouldn't do that in real code

    connect(&p, SIGNAL(finished(int)), this, SLOT(quit()));
    //connect(this, SIGNAL(signalTerminateProcess()), &p, SLOT(kill())); // queued connect that doesn't kill my process

    p.start(cmd);
    while(! p.waitForFinished(100)) //Wake up every 100ms and check if we must exit
    {
        QCoreApplication::processEvents();
    }
    qInfo("process done");
    process = nullptr;
}

int cleanUp()
{
    QTimer::singleShot(0, process, &QProcess::terminate);
    // Qt 5.10 -> QMetaObject::invokeMethod(process, &QProcess::terminate);
    if (! thread->wait(1000))
    {
        QTimer::singleShot(0, process, &QProcess::kill);
        thread->wait();
    }
}
// Create thread
QThread thread;
thread.start();

// Create process and move it to the other thread
QProcess process;
process.moveToThread(&thread);

void startProcess()
{
    p.start(cmd);
}

QMutex mutex;
void stopProcess()
{
    p.terminate();
    if (!p.waitForFinished(1000))
        p.kill();
    p.moveToThread(qApp->thread());
    mutex.unlock();
}

// Call startProcess() in the other thread
QTimer::singleShot(0, &process, &startProcess);

// Call stopProcess() in the other thread
mutex.lock();
QTimer::singleShot(0, &process, &stopProcess);
mutex.lock();

thread.quit();
if (!thread.wait(100))
    thread.terminate();