线程异步操作
void CASyncTestDlg::OnBnClickedButton1()
{// 检查 future 对象是否有效(是否关联了一个异步任务)if (_future.valid()) {// 检查异步任务是否已经完成(在1毫秒内是否能完成等待)if (std::future_status::ready == _future.wait_for(std::chrono::milliseconds(1))) {// 如果已完成,获取任务结果(对于void任务,这主要是清理状态)_future.get();} else {// 如果任务还在运行,弹出消息框提示用户AfxMessageBox(_T("异步任务执行中"));return; // 退出函数,不启动新任务}}// 启动一个新的异步任务_future = std::async(std::launch::async, [this]() {this->DoAsyncWork(); // 在新线程中执行这个函数});
}
逐词详细解释
1.
_future.valid()
_future
:这是一个std::future
类型的成员变量,可以看作是一张"任务提货单"或"任务凭证"。
.valid()
:检查这张"提货单"是否有效(是否关联了一个真实的异步任务)。作用:检查是否已经有一个异步任务存在。
2.
std::future_status::ready
std::future_status
:这是一个枚举类型,表示异步任务的状态。
::ready
:枚举值之一,表示任务已经完成,结果已就绪。其他可能值:
timeout
(超时,未完成)、deferred
(延迟执行,尚未开始)。3.
_future.wait_for(std::chrono::milliseconds(1))
.wait_for()
:等待异步任务完成,但只等待指定的时间。
std::chrono::milliseconds(1)
:等待时间为1毫秒。
std::chrono
:C++的时间库
milliseconds
:毫秒时间单位
(1)
:1毫秒作用:检查任务是否能在极短时间内完成(实际上就是检查是否已经完成)。
4.
_future.get()
.get()
:获取异步任务的结果。对于void任务:没有实际返回值,但调用它会清理future的状态,使valid()返回false。
重要特性:如果任务还未完成,
.get()
会阻塞当前线程直到任务完成。5.
AfxMessageBox(_T("异步任务执行中"))
AfxMessageBox()
:MFC框架中显示消息框的函数。
_T("...")
:MFC中的宏,用于创建 Unicode 或 ANSI 字符串(取决于项目设置)。作用:弹出提示框,告诉用户任务正在执行中。
6.
std::async(std::launch::async, [this]() { ... })
std::async
:C++11标准库函数,用于启动异步任务。
std::launch::async
:启动策略,表示立即在新线程中异步执行任务。
另一种策略:
std::launch::deferred
(延迟执行,直到调用get()时才执行)
[this]() { ... }
:Lambda表达式(匿名函数)
[this]
:捕获列表,表示Lambda中可以访问当前类的成员
()
:参数列表(此处无参数)
{ this->DoAsyncWork(); }
:函数体,调用当前类的DoAsyncWork方法7.
_future = ...
将
std::async
返回的future对象赋值给成员变量_future
。这样下次点击按钮时就可以检查这个任务的状态了。
与Qt版本的对比
MFC (C++11标准库) | Qt框架 | 说明 |
---|---|---|
std::async | QtConcurrent::run | 启动异步任务 |
std::future | QFuture + QFutureWatcher | 管理异步任务 |
_future.valid() | QFutureWatcher::isRunning() | 检查任务状态 |
_future.wait_for() | 信号槽自动通知 | 等待任务完成 |
AfxMessageBox | QMessageBox::information | 显示提示框 |
Qt
void AsyncTestDialog::on_btnStart_clicked()
{// 检查是否已有任务在运行if (m_futureWatcher.isRunning()) {QMessageBox::information(this, "提示", "异步任务执行中");return;}// 禁用按钮,防止重复点击ui->btnStart->setEnabled(false);ui->labelStatus->setText("任务执行中...");// 使用QtConcurrent在后台线程中运行异步任务QFuture<void> future = QtConcurrent::run(doAsyncWork, this);m_futureWatcher.setFuture(future);
}
1.
m_futureWatcher.isRunning()
m_futureWatcher
:这是一个QFutureWatcher<void>
类型的成员变量,用于监控异步任务的状态。
.isRunning()
:检查监视器是否正在监控一个运行中的任务。作用:防止用户重复点击按钮启动多个并发任务。
2.
QMessageBox::information(this, "提示", "异步任务执行中")
QMessageBox
:Qt 中用于显示消息对话框的类。
::information()
:静态方法,显示一个信息提示框。参数:
this
:父窗口指针,确保对话框居中显示
"提示"
:对话框标题
"异步任务执行中"
:对话框内容作用:给用户友好的提示,告知任务正在执行中。
3.
ui->btnStart->setEnabled(false)
ui
:指向UI界面的指针(通常由Qt Designer生成)。
->btnStart
:访问界面上的按钮组件(假设按钮的对象名为"btnStart")。
->setEnabled(false)
:禁用按钮,使其不可点击。作用:防止用户在任务执行期间重复点击按钮。
4.
ui->labelStatus->setText("任务执行中...")
->labelStatus
:访问界面上的标签组件(假设标签的对象名为"labelStatus")。
->setText("...")
:设置标签显示的文本。作用:给用户提供视觉反馈,显示当前任务状态。
5.
QtConcurrent::run(doAsyncWork, this)
QtConcurrent
:Qt 的并发编程命名空间,提供高级API简化多线程编程。
::run()
:静态函数,用于在后台线程中运行函数。参数:
doAsyncWork
:要执行的函数指针(必须是静态函数或全局函数)
this
:传递给函数的参数(此处传递当前对象的指针)返回值:返回一个
QFuture<void>
对象,表示异步计算。6.
QFuture<void> future = ...
QFuture<void>
:模板类,表示一个异步计算的结果。
<void>
:表示这个异步任务不返回任何值。
future
:局部变量,存储QtConcurrent::run()
返回的 future 对象。作用:获取对异步任务的引用,以便后续监控。
7.
m_futureWatcher.setFuture(future)
.setFuture(future)
:将 future 对象设置给监视器,开始监控任务状态。作用:连接异步任务和监视器,使得监视器能够发出任务状态变化的信号。