Do信号创建新线程
Do signals create new threads?
我正在努力了解信号/插槽在GUI程序中是如何工作的。例如,如果主程序中的一个插槽收到信号,它是否会创建另一个线程来处理该插槽?
主窗口.h
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void finished_result(int);
private:
Ui::MainWindow *ui;
QThread* thread;
Worker* worker;
private slots:
void run_click();
};
主窗口.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),ui(new Ui::MainWindow){
ui->setupUi(this);
}
MainWindow::~MainWindow(){
delete ui;
}
void MainWindow::run_click(){
thread = new QThread;
Worker* worker = new Worker();
worker->moveToThread(thread);
connect(worker,SIGNAL(task_finished(int)),this,SLOT(finished_result(int)));
// all other necessary signal/slot connections
thread->start();
// do more stuff
}
void MainWindow::finished_result(int x){
// do some stuff
}
在这样的程序中,说"做更多的事情"需要一段时间来处理,工人在run_click()
返回之前完成工作。因此,当task_finished(int)
发出时,run_click()
仍将运行。finished_result(int)
会立即启动还是等待run_click()
完成?finished_result(int)
是在与run_click()
相同的线程中启动,还是在新线程中启动?
我的特殊问题是,在我的"做更多的事情"中有一个不相关的QWaitCondition
,它会占用该线程一段时间。我希望我的finished_result(int)
继续进行,而不必等待run_click()
完成。有什么想法可以继续吗?我是否需要将"做更多的事情"转移到新线程中的另一个工作者?
在您的情况下,run_click()
和finished_result(int x)
将在同一线程中按此顺序执行。当信号task_finished(int)
从工作线程发出时,它将被传输并在主线程的队列中等待,等待run_click()
完成,从而返回事件循环。只有到那时才会调用finished_result(int x)
。
这被称为"排队连接",是在不同线程中使用信号和插槽时的默认行为。请查看文档中的线程和QObjects以获取更多信息,特别是跨线程的信号和插槽部分。
Boris(+1)的好答案
我只想补充一下你的第二个问题,你希望在不等待run_click()的情况下处理finished_result(),那么如果你希望它"安全"运行,你需要将其放入另一个线程(并将其全部连接起来)。
你可能读到Qt确实允许你强制连接为"DirectConnection",在那里信号一收到就被处理,这是同一线程内信号的默认设置,但跨线程这样做是非常危险的,所以不要被这个选项所诱惑!
可能还有第三个选项可以暂停当前事件并在事件队列中查找下一个项目。。但我不确定,我想我以前读过这样的东西,但找不到…也许有人能回答这个部分?(我会看一看是否能找到这个)。
- 在挂钩启动新线程时解除挂钩进程
- 如何检查第三个 API 是否在 Linux 中为 c/c++ 程序创建了一个新线程?
- C++中的多线程:连接线程的正确方法
- 是否需要在 Timer.5 boost::asio 教程中运行新线程?
- SetTimer (带有回调函数)是否通过启动新线程来工作?
- Zmq 上下文 - 我应该在新线程中创建另一个上下文吗?
- 函数如何在不这样做的情况下在新线程上运行"as if"?
- 从 VS2013 到 VS2017 std::async 不会启动新线程
- 从传递给新线程C++的矢量中删除项目
- c++ 从成员函数创建新线程并移动对象和整个对象
- 在新线程C++中发送 http 请求
- 在新线程中访问移动的 std::string
- 使用新线程在类似于 Scott Meyer 的单例习惯用法的实现中实例化单例是否安全?
- Winapi:在类成员功能上创建新线程 - 不兼容的参数类型
- 使用新线程池而无需重新启动的新线程池后,Jemalloc的内存大大增加
- C++ std::async 不会生成新线程
- 如何在 Linux 上强制 g++ 在协程切换线程时更新线程指针(对于 TLS)
- 一旦另一个线程完成,就会生成一个新线程
- 只在前一个线程完成时创建一个新线程
- 创建新线程时在lambda内部使用unique_ptr的线程安全性