C++std::在主线程上异步运行
C++ std::async run on main thread
有没有办法在主线程上运行函数?
因此,如果我通过Async调用一个函数,该函数下载了一个文件,然后解析了数据。然后它会调用一个回调函数,该函数将在我的主UI线程上运行并更新UI?
我知道线程在默认的C++实现中是相等的,所以我必须创建一个指向主线程的共享指针。我该如何做到这一点,并将异步函数不仅传递到主线程的共享指针,还传递到我想在其上运行的函数的指针,然后在该主线程上运行它?
我一直在阅读C++操作中的并发,第四章(又名"第一章刚刚完成")描述了一个解决方案。
简短版本
有一个共享的std::deque<std::packaged_task<void()>>
(或类似类型的消息/任务队列)。std::async
启动的函数可以将任务推送到队列,GUI线程可以在循环过程中处理它们。
虽然没有很长的版本,但这里有一个例子
共享数据
std::deque<std::packaged_task<void()>> tasks;
std::mutex tasks_mutex;
std::atomic<bool> gui_running;
std::async
函数
void one_off()
{
std::packaged_task<void()> task(FUNCTION TO RUN ON GUI THREAD); //!!
std::future<void> result = task.get_future();
{
std::lock_guard<std::mutex> lock(tasks_mutex);
tasks.push_back(std::move(task));
}
// wait on result
result.get();
}
GUI线程
void gui_thread()
{
while (gui_running) {
// process messages
{
std::unique_lock<std::mutex> lock(tasks_mutex);
while (!tasks.empty()) {
auto task(std::move(tasks.front()));
tasks.pop_front();
// unlock during the task
lock.unlock();
task();
lock.lock();
}
}
// "do gui work"
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
}
注意事项:
我(一直)在学习,所以我的代码很有可能不太好。不过,这个概念至少是合理的。
std::async
(一个std::future<>
)返回值的析构函数将阻塞,直到用std::async
启动的操作完成(请参见std::async
),因此在one_off
中等待任务的结果(就像我在示例中所做的那样)可能不是一个好主意。您可能想要(至少我会)创建自己的线程安全MessageQueue类型,以提高代码的可读性/可维护性等等。
我发誓还有一件事我想指出,但我现在想不出来了。
完整示例
#include <atomic>
#include <chrono>
#include <deque>
#include <iostream>
#include <mutex>
#include <future>
#include <thread>
// shared stuff:
std::deque<std::packaged_task<void()>> tasks;
std::mutex tasks_mutex;
std::atomic<bool> gui_running;
void message()
{
std::cout << std::this_thread::get_id() << std::endl;
}
void one_off()
{
std::packaged_task<void()> task(message);
std::future<void> result = task.get_future();
{
std::lock_guard<std::mutex> lock(tasks_mutex);
tasks.push_back(std::move(task));
}
// wait on result
result.get();
}
void gui_thread()
{
std::cout << "gui thread: "; message();
while (gui_running) {
// process messages
{
std::unique_lock<std::mutex> lock(tasks_mutex);
while (!tasks.empty()) {
auto task(std::move(tasks.front()));
tasks.pop_front();
// unlock during the task
lock.unlock();
task();
lock.lock();
}
}
// "do gui work"
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
}
int main()
{
gui_running = true;
std::cout << "main thread: "; message();
std::thread gt(gui_thread);
for (unsigned i = 0; i < 5; ++i) {
// note:
// these will be launched sequentially because result's
// destructor will block until one_off completes
auto result = std::async(std::launch::async, one_off);
// maybe do something with result if it is not void
}
// the for loop will not complete until all the tasks have been
// processed by gui_thread
// ...
// cleanup
gui_running = false;
gt.join();
}
Dat输出
$ ./messages
main thread: 140299226687296
gui thread: 140299210073856
140299210073856
140299210073856
140299210073856
140299210073856
140299210073856
你在找std::launch::deferred
吗?当第一次调用get()函数时,将此参数传递给std::async会使任务在调用线程上执行。
相关文章:
- 运行同一解决方案的另一个项目的项目
- 在 c++ 托管和异步运行中调用 c# 可执行文件
- Qt异步调用:如何在异步调用完成任务后运行一些东西
- Win32 函数可以在同一线程上异步运行吗?
- 如何使用 boost::asio io_service 运行函数异步
- C++ 异步仅在一个内核上运行?
- 运行 boost::asio 异步服务器以及命令循环
- 在我的CUDA运行时间计划中,CPU和GPU可以异步计算,但不能合作地计算
- 在c++中使用回调异步运行linux命令
- C++:如何运行一个系统命令N次(异步)并返回N次执行时间
- 在 boost::asio 中启动异步操作和运行io_service的正确顺序
- 为什么C++异步按顺序运行而没有未来
- C++,OpenCV:异步运行cuda::dft
- libuv(node.js的异步库)可以在Apple IOS / Android上运行吗?
- C++std::在主线程上异步运行
- std::异步函数串行运行
- Googletest:如何异步运行测试
- 在V8中异步运行c++和JS代码
- 同时运行的c++异步线程
- 从c++中运行CURL以异步获取多个url