使用 std::bind 将 QTimer::singleShot 传递给 std::async
Pass QTimer::singleShot to std::async using std::bind
以下代码启动一个非阻塞计时器,该计时器将在一秒后启动函数 myFunc
:
MyClass.h:
std::future<void> timer_future_;
MyClass.cpp:
timer_future_ = std::async(
std::launch::async,
[this] { QTimer::singleShot(1000,
[this] {this->myFunc();}
);
}
);
我想用 std::function
s 替换 lambda 函数。我已经成功替换了第二个 lambda,如下所示:
timer_future_ = std::async(
std::launch::async,
[this] { QTimer::singleShot(1000,
std::bind(&MyClass::myFunc, this)
);
}
);
现在如何用另一个 std::bind()
调用替换第一个 lambda?
请注意,函数 QTimer::singleShot
来自 Qt 库;它的文档是 here。它的原型是:
void QTimer::singleShot(int msec, Functor functor)
根据 this question, the definition of the Functor type can be found in QObject.h
。它说:
template <class FunctorT, class R, typename... Args> class Functor { /*...*/ }
经过一些研究,我了解到将替换第一个 lambda 的 std::bind()
必须考虑以下因素:
QTimer::singleShot
是重载函数,所以I must use a cast to disambiguate the call to it
QTimer::singleShot
是静态成员函数,所以the pointer to it must resemble a pointer to a non-member function
我试过几次都不成功,最后一次是:
timer_future_ = std::async(
std::launch::async,
std::bind( ( void(*) (int, Functor<const std::function<void(void)>,void>) )&QTimer::singleShot,
1000,
std::bind(&MyClass::myFunc, this)
)
);
对于这段代码,MSVC 编译器返回了错误信息
error: C2059: syntax error: ')'
在第三行。
为什么我不直接使用已经工作的 lambda 表达式? 答案很简单,尝试使用 std::bind() 反而让我学到了更多关于C++语言的各种特性以及如何使用它们。
编辑: 实现 Kuba Ober 答案的代码:
QTimer::singleShot(1000, [this] {
timer_future_ = std::async(
std::launch::async,
std::bind(&MyClass::myFunc, this)
);
});
计算左括号和右括号并添加分号
计时器需要一个事件循环,std::async
将在没有 运行ning 事件循环的工作线程中调用它。我怀疑你为什么要这样做?
如果您想 运行 延迟后在工作线程中执行某些操作,运行 具有事件循环的线程中的计时器,并从该计时器触发异步操作。
以下代码启动一个非阻塞计时器,该计时器将在一秒后启动函数 myFunc
:
MyClass.h:
std::future<void> timer_future_;
MyClass.cpp:
timer_future_ = std::async(
std::launch::async,
[this] { QTimer::singleShot(1000,
[this] {this->myFunc();}
);
}
);
我想用 std::function
s 替换 lambda 函数。我已经成功替换了第二个 lambda,如下所示:
timer_future_ = std::async(
std::launch::async,
[this] { QTimer::singleShot(1000,
std::bind(&MyClass::myFunc, this)
);
}
);
现在如何用另一个 std::bind()
调用替换第一个 lambda?
请注意,函数 QTimer::singleShot
来自 Qt 库;它的文档是 here。它的原型是:
void QTimer::singleShot(int msec, Functor functor)
根据 this question, the definition of the Functor type can be found in QObject.h
。它说:
template <class FunctorT, class R, typename... Args> class Functor { /*...*/ }
经过一些研究,我了解到将替换第一个 lambda 的 std::bind()
必须考虑以下因素:
QTimer::singleShot
是重载函数,所以I must use a cast to disambiguate the call to itQTimer::singleShot
是静态成员函数,所以the pointer to it must resemble a pointer to a non-member function
我试过几次都不成功,最后一次是:
timer_future_ = std::async(
std::launch::async,
std::bind( ( void(*) (int, Functor<const std::function<void(void)>,void>) )&QTimer::singleShot,
1000,
std::bind(&MyClass::myFunc, this)
)
);
对于这段代码,MSVC 编译器返回了错误信息
error: C2059: syntax error: ')'
在第三行。
为什么我不直接使用已经工作的 lambda 表达式? 答案很简单,尝试使用 std::bind() 反而让我学到了更多关于C++语言的各种特性以及如何使用它们。
编辑: 实现 Kuba Ober 答案的代码:
QTimer::singleShot(1000, [this] {
timer_future_ = std::async(
std::launch::async,
std::bind(&MyClass::myFunc, this)
);
});
计算左括号和右括号并添加分号
计时器需要一个事件循环,std::async
将在没有 运行ning 事件循环的工作线程中调用它。我怀疑你为什么要这样做?
如果您想 运行 延迟后在工作线程中执行某些操作,运行 具有事件循环的线程中的计时器,并从该计时器触发异步操作。