嗨,我有一个名为search的类,该类有两个成员函数。消费者和生产者。这就是我在qt中将这些功能激活为两个线程的方式。
for usr in User.objects.all():
backend_list = []
if usr.has_usable_password():
backend_list.append('ModelBackend')
if ... : # what should I check here ?
backend_list.append('OtherBackend')
print(usr, backend_list)
但是,似乎只有一个被激活。我应该如何同时激活两者。请让我知道一个例子。
谢谢。
答案 0 :(得分:0)
这是一个简单的示例,可以在两个不同的线程中运行同一对象的两个方法。假设您的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
仅在该线程有效时有效返回到事件循环!如果您的生产者/消费者方法没有不返回事件循环并使用它来执行任务,请在注释中写上这样,我也将更新答案以处理这种情况。
编辑:由于仅在上述解决方案中起作用,因此如果生产者/消费者返回到事件循环(根据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
并优雅地停止您的应用程序,将其作为默认{{1} }会终止它,而没有适当的清理