簡體   English   中英

殺死在其他QThread中運行的QProcess

[英]Kill a QProcess running in a different QThread

我有一個繼承QThread的類,並重新實現了run()方法。 在此運行方法中,有一個QProcess (在運行中聲明)啟動程序。

現在,如果在該進程仍在運行時關閉我的應用程序,則實際上直到該進程完成,它才會關閉。

所以我的問題是如何停止該過程?

根據我在Qt文檔中所讀的內容,我無法在此處使用信號/插槽,因為我的進程將與不是主線程的線程具有線程親和力,因此連接處於排隊狀態,這不會停止我的進程。

我正在使用Qt 5.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使用信號和插槽,甚至可以使用Qt::BlockingQueuedConnection等待插槽執行。 請參閱Qt文檔

但是,這要求目標QObject駐留在具有正在運行的事件循環的線程中。 在您的情況下,由於您已重載QThread::run() ,因此將沒有事件循環。

正如我所看到的,您有2種修復代碼的方法,要么做一個小的修復,要么更改設計並使用事件循環。

1.快速修復

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

2.事件循環修復

// 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連接的信號來替換互斥鎖。
  • 用插槽和lambda替換startProcess()stopProcess()
  • 通過QMetaObject::invokeMethod()或使用信號來替換對QTimer::singleShot() QMetaObject::invokeMethod() QTimer::singleShot()QMetaObject::invokeMethod() 請注意,您可以將Qt::BlockingQueuedConnectionQMetaObject::invokeMethod()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM