Jam*_*ell 12 c++ multithreading asynchronous std c++11
有没有办法在主线程上运行一个函数?
因此,如果我通过Async调用一个函数来下载文件,然后解析数据.然后它将调用一个回调函数,该函数将在我的主UI线程上运行并更新UI?
我知道在默认的C++实现中线程是相同的,所以我必须创建一个指向我的主线程的共享指针.我如何做到这一点,并将Async函数不仅传递给主线程的共享指针,还传递指向我想要在其上运行的函数的指针,然后在该主线程上运行它?
小智 12
我一直在阅读C++ Concurrency in Action和第四章(AKA"The Chapter I Just Finished")描述了一个解决方案.
拥有共享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;
Run Code Online (Sandbox Code Playgroud)
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();
}
Run Code Online (Sandbox Code Playgroud)
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));
}
}
Run Code Online (Sandbox Code Playgroud)
我(总是)在学习,所以我的代码不太好.这个概念至少是合理的.
来自std::async(a 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();
}
Run Code Online (Sandbox Code Playgroud)
$ ./messages
main thread: 140299226687296
gui thread: 140299210073856
140299210073856
140299210073856
140299210073856
140299210073856
140299210073856
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
13320 次 |
| 最近记录: |