[英]Kill a QProcess running in a different QThread
I have a class that inherits QThread
and I reimplemented the run()
method. 我有一个继承QThread
的类,并重新实现了run()
方法。 In this run method, there's a QProcess
(declared in run) that starts a program. 在此运行方法中,有一个QProcess
(在运行中声明)启动程序。
Now if I close my application while that process is still running, it actually won't close until the process finishes. 现在,如果在该进程仍在运行时关闭我的应用程序,则实际上直到该进程完成,它才会关闭。
So my question is how do I stop this process ? 所以我的问题是如何停止该过程?
From what I've read in Qt docs, I cannot use signal/slot here since my process will have thread affinity with a thread that is not the main thread, so the connections are queued and this doesn't stop my process. 根据我在Qt文档中所读的内容,我无法在此处使用信号/插槽,因为我的进程将与不是主线程的线程具有线程亲和力,因此连接处于排队状态,这不会停止我的进程。
I'm using Qt 5.8 我正在使用Qt 5.8
Thanks in advance ! 提前致谢 !
EDIT: here's the thread code, let me know if you need more 编辑:这是线程代码,让我知道是否需要更多
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");
}
}
First, you can use signal & slots across QThreads and you can even wait for the slot to be executed using Qt::BlockingQueuedConnection
. 首先,您可以跨QThreads使用信号和插槽,甚至可以使用Qt::BlockingQueuedConnection
等待插槽执行。 See Qt documentation . 请参阅Qt文档 。
However, this requires the target QObject to live in a thread that has a running event loop. 但是,这要求目标QObject驻留在具有正在运行的事件循环的线程中。 In your case, since you have overloaded QThread::run()
, you will not have an event loop. 在您的情况下,由于您已重载QThread::run()
,因此将没有事件循环。
As I see it, you have 2 ways of fixing your code either you do a small fix or you change the design and use the event loop. 正如我所看到的,您有2种修复代码的方法,要么做一个小的修复,要么更改设计并使用事件循环。
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();
}
or 要么
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();
You can : 您可以 :
Qt::BlockingQueuedConnection
. 通过使用原子或使用与Qt::BlockingQueuedConnection
连接的信号来替换互斥锁。 startProcess()
and stopProcess()
by slots and lambdas. 用插槽和lambda替换startProcess()
和stopProcess()
。 QTimer::singleShot()
by QMetaObject::invokeMethod()
or by using signals. 通过QMetaObject::invokeMethod()
或使用信号来替换对QTimer::singleShot()
QMetaObject::invokeMethod()
QTimer::singleShot()
的QMetaObject::invokeMethod()
。 Note thate you can use Qt::BlockingQueuedConnection
with QMetaObject::invokeMethod()
请注意,您可以将Qt::BlockingQueuedConnection
与QMetaObject::invokeMethod()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.