首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >杀死运行在不同QThread中的QThread

杀死运行在不同QThread中的QThread
EN

Stack Overflow用户
提问于 2017-10-13 15:36:26
回答 1查看 1.6K关注 0票数 0

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

现在,如果我在进程仍在运行时关闭我的应用程序,它实际上在进程结束之前不会关闭。

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

根据我在Qt文档中所读到的内容,我不能在这里使用信号/插槽,因为我的进程将与一个不是主线程的线程有关联,所以连接是排队的,这并不会停止我的进程。

我用的是Qt 5.8

提前谢谢!

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

代码语言:javascript
复制
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");
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-10-13 16:46:55

首先,您可以跨QThreads使用信号和插槽,甚至可以等待使用Qt::BlockingQueuedConnection执行时隙。见Qt文档

但是,这需要目标QObject驻留在一个具有正在运行的事件循环的线程中。在您的例子中,由于您已经重载了QThread::run(),所以您将不会有一个事件循环。

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

1.快速修复

代码语言:javascript
复制
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();
}

代码语言:javascript
复制
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();
    }
}

2.事件循环修复

代码语言:javascript
复制
// 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();

你可以:

  • 使用原子或与Qt::BlockingQueuedConnection连接的信号替换互斥体。
  • 用插槽和lambdas替换startProcess()stopProcess()
  • 将对QTimer::singleShot()的调用替换为QMetaObject::invokeMethod()或使用信号。注意,您可以将Qt::BlockingQueuedConnectionQMetaObject::invokeMethod()结合使用。
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46733421

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档