QThreadPool::waitForDone()可阻塞线程,采用std::function方式将其置于其它线程执行,避免阻塞线程同时可设置等待框(其它线程)生存期,单纯不阻塞线程可以直接不使用waitForDone。
一.调用
DlgProcess wait(QString("检查中"));
wait.WaitFor([&]()//std::function<void()>& task //&表示引用传递捕捉所有父作用域变量
{
m_pThreadPool->waitForDone();//猜测只有在此函数作用域内wait导致m_pProgress有效
});
二.DlgProcess
DlgProcess::DlgProcess(QWidget *parent) :
QDialog(parent),
ui(new Ui::DlgProcess)
{
ui->setupUi(this);
m_timer=new QTimer(this);
connect(m_timer, SIGNAL(timeout()), this, SLOT(UpdateMsg()));//每隔1秒刷新
m_nDotjs=0;
m_nStep=0;
}
DlgProcess::~DlgProcess()
{
delete ui;
}
void DlgProcess::WaitFor(const std::function<void()>& task)
{
int w = 200;
int h = 100;
//设置显示位置
this->setFixedSize(w,h);
QDesktopWidget* deskWidget = QApplication::desktop();
QRect deskRect = deskWidget->availableGeometry();//QDesktopWidget
double x = (deskRect.width() -w)/2; //设置对话框居中于桌面
double y = (deskRect.height()-h)/2;
this->move(x,y);
this->setWindowModality(Qt::ApplicationModal);
m_timer->start(1000);//每隔1秒刷新
this->m_task = task;//std::function<void()>
//this->exec();//触发showEvent
if (m_task != nullptr)
{
m_thread = new ThreadTask(this,this->m_task);//设置多线程,任务结束时关闭
m_thread->start();
}
}
void DlgProcess::setStep(int nStep)
{
ui->progressBar->setValue(nStep);
//update();//会调用
}
void DlgProcess::SetMsg(QString sMsg)//修改文本
{
m_sMsg=sMsg;
//ui->label->setText(m_sMsg);
}
void DlgProcess::UpdateMsg()
{
//刷新下面文字
QString sMsg=m_sMsg;
for(int i=0;i<m_nDotjs;i++)
{
sMsg+=".";
}
++m_nDotjs;
if(m_nDotjs>3) m_nDotjs=0;
ui->label->setText(sMsg);
update();
}
void DlgProcess::showEvent(QShowEvent *event)//初次显示时触发
{
if (m_task != nullptr)
{
m_thread = new ThreadTask(this,this->m_task);//设置多线程,任务结束时关闭
m_thread->start();
}
}
三.waitForDone移至QThread运行
ThreadFun::ThreadFun(const std::function<void()>& task)
{
this->m_task = task;
}
void ThreadFun::run()
{
if (this->m_task != nullptr)
this->m_task();//猜测将外部函数移至线程内执行,此处可避免主界面阻塞
emit taskFinish();
}