标题:从UI线程给子线程发信号,为什么没有被执行槽函数?
作者:stlcours
日期:2016-09-30 05:02
内容:
我做了一个功能,允许用户删除某个目录下的全部文件,删除的时候有一个进度条对话框和一个按钮,允许用户中断这个过程。
MyDialog::OnCancel()
{
emit SigCancel(); // 发信号给MyThread::OnStop()槽函数
}
MyThread::OnStop()
{
// 会收到信号并执行这个函数
this->m_stop = true;
emit SigCancel(); // 再次发送信号。之所以要这样中转,而没有通过MyDialog直接发送给tool对象,是因为tool对象是run()函数里当场申请的对象,没有提前预知。
}
MyThread::run()
{
MyTool tool;
connect(this, signal(SigCancel()), &tool, slot(ChangeVar()));
tool.DeleteAllFiles();
}
MyTool::ChangeVar()
{
// 这个函数的目的是,改变这个类的某个bool变量,使这个类的DeleteAllFiles()能够早点跳出这个循环
m_not_delete = true;
}
MyTool::DeleteAllFiles()
{
for (i=0; i
#1 [mu_de_yu 09-30 09:30]
你这样写,不闲的很麻烦吗,来回发信号,我建议你为何不把DeleteAllFiles()功能改为删除一个文件功能。然后在run里循环调用,达到删除所有文件的目的。run 这样写:
while(1){
if(flag_stop_delete){
// 在这里执行删除单个文件函数
}
... ...
QThread::sleep(1);
}
当你的OnStop()响应时,在里面将flag_stop_delete置为false即可,删除功能就不再执行
#2 [mu_de_yu 09-30 09:39]
针对你的问题:
两个问题起始是一个问题:
信号槽响应也是正常的函数调用,遵循事件队列先后执行,你的子线程在删除文件(一直循环),信号发送和槽函数响应也是你子线程执行的,所以只会在你循环结束后才会调用
#3 [dbzhang800 09-30 10:23]
你的用法是错误的,它不可能工作的。
首先:你的 connect 用的是 Qt::AutoConnection 方式。
其次:你需要知道,你的MyThread::OnStop()是在主线程执行,它里面的信号肯定就是在主线程
再次:你的tool对象在次线程创建,与信号不在同一个线程。所以你的connect此时等效于 Qt::QueuedConnection
再再次:你的次线程内压根没有事件循环,信号对应的事件不可能被次线程收到。更没办法让事件系统调用你的槽函数了。
#4 回 dbzhang800 的帖子 [stlcours 09-30 15:42]
dbzhang800:你的用法是错误的,它不可能工作的。
首先:你的 connect 用的是 Qt::AutoConnection 方式。
其次:你需要知道,你的MyThread::OnStop()是在主线程执行,它里面的信号肯定就是在主线程
再次:你的tool对象在次线程创建,与信号不在同一个线程。所以你的connect此时等效于 Qt::Que .. (2016-09-30 10:23)
请问你说的次线程没有事件循环队列,是指什么?应该怎么加上?
没有事件循环队列就不能使用信号槽吗?我在这个次线程tool里使用emit调用主线程的对话框没有任何问题啊。
#5 回 mu_de_yu 的帖子 [stlcours 09-30 15:45]
mu_de_yu:你这样写,不闲的很麻烦吗,来回发信号,我建议你为何不把DeleteAllFiles()功能改为删除一个文件功能。然后在run里循环调用,达到删除所有文件的目的。run 这样写:
while(1){
if(flag_stop_delete){
// 在这里执行 .. (2016-09-30 09:30)
你这个回答很简洁有力。但我是把问题模型简化了的。MyTool类里,有一堆的相关函数需要调用。最好把这些功能都写在MyTool类里。如果实在没办法,也就只有把那部分代码单独拿出来放到run里了。