gpt4 book ai didi

c++ - 从另一个线程打破循环

转载 作者:行者123 更新时间:2023-11-30 04:54:40 24 4
gpt4 key购买 nike

目前我有两个看起来像这样的类:

class Worker : public QObject
{
Q_OBJECT

bool aborted = false;

public:
Worker() : QObject() {}

public slots:
void abort() { aborted = true; }

void doWork()
{
while(!aborted && !work_finished)
{
//do work
QCoreApplication::processEvents();
}
}
};

class Controller : public QObject
{
Q_OBJECT

QThread workerThread;
public:
Controller() : QObject()
{
Worker *worker = new Worker;
worker->moveToThread(&workerThread);
connect(&workerThread, &QThread::finished, worker, &Worker::deleteLater);
connect(this, &Controller::startWork, worker, &Worker::doWork);
connect(this, &Controller::aborted, worker, &Worker::abort);
}

signals:
void startWork();
void aborted();
};

Controller *cont = new Controller;
emit cont->startWork(); // Start the loop
emit cont->aborted(); // Stop the loop

所以想法是在 Worker 线程中运行一个循环,它可以从 Controller 线程中停止。

在示例中,这是通过调用 QCoreApplication::processEvents() 完成的,它允许信号在将控制权返回给循环之前调用槽。
重要的是循环仅在迭代开始或结束时停止。

虽然这很好用,但我认为 QCoreApplication::processEvents() 非常昂贵,至少在一个很长的循环(在实践中高达数千个)中使用时是这样。

所以我的问题是,如何以更好/更便宜的方式实现相同的结果?

最佳答案

目前我知道三种替代解决方案。

1。 QThread::requestInterruption (由@Felix 建议)

根据 QThread::isInterruptionRequested :

Take care not to call it too often, to keep the overhead low.

QCoreApplication::processEvents对性能或内存使用没有任何评论,所以我不认为 QThread::requestInterruption 在这种情况下是对 QCoreApplication::processEvents 的改进。


2。 std::atomic (由@Felix 建议)

The main characteristic of atomic objects is that access to this contained value from different threads cannot cause data races [...]

bool 值可以存储在 std::atomic 中,它可以成为 Controller 类而不是 Worker 类的成员.然后我们需要将对aborted的引用传递给Worker并将其存储在Worker中,并从Controller中将其设置为true > 需要时。

我没有完全测试这个方法,所以如果我有什么不对的地方,请纠正我。

class Worker : public QObject {
Q_OBJECT
std::atomic<bool> &aborted;
public:
Worker(std::atomic<bool> &aborted) : QObject(), aborted(aborted) {}
public slots:
void doWork() {
while(!aborted.load() && !work_finished) /* do work */
}
};

class Controller : public QObject {
Q_OBJECT
QThread workerThread;
std::atomic<bool> aborted;
public:
Controller() : QObject() {
aborted.store(false);
Worker *worker = new Worker(aborted);
worker->moveToThread(&workerThread);
connect(&workerThread, &QThread::finished, worker, &Worker::deleteLater);
connect(this, &Controller::startWork, worker, &Worker::doWork);
connect(this, &Controller::aborted, worker, &Worker::abort);
}

void abort() { aborted.store(true); }
signals:
void startWork();
};

Controller *cont = new Controller;
emit cont->startWork(); // Start the loop
cont->abort(); // Stop the loop

3。 QWaitCondition & QMutex

将需要一个 bool 值 pausedControllerWorker 需要对其进行读/写访问。

需要时在Controller中将paused设置为true
Worker 的循环中,if(paused):QWaitCondition::wait()直到 QWaitCondition::wakeAll()从调用线程调用。
QMutex::lock每当访问 paused 时都需要调用。

class Worker : public QObject {
Q_OBJECT
bool &aborted, &paused;
QWaitCondition &waitCond;
QMutex &mutex;
public:
Worker(bool &aborted, bool &paused, QWaitCondition &waitCond, QQMutex &mutex)
: QObject(), aborted(aborted), paused(paused), waitCond(waitCond), mutex(mutex) {}
public slots:
void doWork() {
while(!aborted && !work_finished) {
//do work
mutex.lock();
if(paused) {
waitCond.wait(&mutex);
paused = false;
}
mutex.unlock();
}
}

void abort() { aborted = true; }
};

class Controller : public QObject {
Q_OBJECT
bool aborted=false, paused=false;
QWaitCondition waitCond;
QMutex mutex;
QThread workerThread;
public:
Controller() : QObject() {
Worker *worker = new Worker(aborted, paused, waitCond, mutex);
worker->moveToThread(&workerThread);
connect(&workerThread, &QThread::finished, worker, &Worker::deleteLater);
connect(this, &Controller::startWork, worker, &Worker::doWork);
}
void abort() {
mutex.lock();
paused = true; // Worker starts waiting
mutex.unlock();

if(confirmed_by_user) aborted = true; // Don't need to lock because Worker is waiting
waitCond.wakeAll(); // Worker resumes loop
}
signals:
void startWork();
};

Controller *cont = new Controller();
emit cont->startWork(); // Start the loop
cont->abort(); // Stop the loop

关于c++ - 从另一个线程打破循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53457805/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com