Это простой пример запуска двух методов одного и того же объекта в двух разных потоках.Предполагая, что ваш Search
класс выглядит следующим образом:
class Search : public QObject
{
Q_OBJECT
public:
void producer();
void consumer();
signals:
void workRequested();
void finishedscan();
};
Вы бы создали второй класс следующим образом:
class Worker : public QObject
{
Q_OBJECT
public:
Worker(std::function<void()> task) :
QObject{},
_task{std::move(task)}
{}
public slots:
void work() {
_task();
}
private:
std::function<void()> _task;
};
И теперь вы можете реализовать начало:
thread1 = new QThread();
thread2 = new QThread();
mySearch = new Search();
auto worker1 = new Worker(std::bind(&Search::producer, mySearch));
auto worker2 = new Worker(std::bind(&Search::consumer, mySearch));
worker1->moveToThread(thread1);
worker2->moveToThread(thread2);
connect(mySearch, SIGNAL(workRequested()), thread1, SLOT(start()));
connect(mySearch, SIGNAL(workRequested()), thread2, SLOT(start()));
connect(thread1, SIGNAL(started()),worker1, SLOT(work()));
connect(thread2, SIGNAL(started()),worker2, SLOT(work()));
connect(mySearch, SIGNAL(finishedscan()), thread1, SLOT(quit()), Qt::DirectConnection);
connect(mySearch, SIGNAL(finishedscan()), thread2, SLOT(quit()), Qt::DirectConnection);
Важно: В то время как это решение решает, как запустить две задачи в разных потоках, остановка пока не будет работать, так как QThread::quit
работает, только если поток возвращается кeventloop!Если методы вашего производителя / потребителя не возвращаются в цикл событий и используют его для выполнения задач, напишите об этом в комментариях, и я обновлю ответ, чтобы обработать и этот случай.
РЕДАКТИРОВАТЬ: Поскольку остановка i, вышеприведенное решение работает только в том случае, если производитель / потребитель возвращаются к циклу событий - что не соответствует требованиям OP, вы должны вручную уведомитьработник, чтобы он прекратил работать, чтобы изящно выйти из потока.
Для первого решения ваш работник должен периодически проверять, должен ли он перестать работать.Например:
MySearch::producer() {
while(!QThread::currentThread()->isInterruptionRequested() {
//do some work
}
}
А во-вторых, вам нужно настроить способ выхода из потока:
connect(mySearch, &MySearch::finishedscan, thread1, [thread1](){
thread1->requestInterruption();
thread1->quit();
}, Qt::DirectConnection);
Примечание: Независимо от того, как вы выходите из своих потоков,вы должны всегда ждать, пока они в главном потоке завершат свою работу перед выходом:
thread1->wait();
Наконец, вы упомянули в комментариях, что вы используете CTRL+C
для выхода из приложения - убедитесь, что зарегистрировали сигналобработчик для перехвата SIGINT
и изящной остановки приложения, так как SIGINT
по умолчанию просто прекратит его, без надлежащей очистки