2014-04-27 33 views
3

如果我从主线程启动thread,是否有任何选项可以挂钩新线程将要触发的回调。应该在主线程中执行回调。是在c + + 11线程node.js/javascript的回调类似的东西?

在我使用future此任务的时刻,但我想避免等待结果(结果是布尔值,如果true一切正常,万一false我需要重新开始线程尝试做任务)。 在C++ 11中类似于node.js/javascript回调的东西吗?

+0

'std :: async'也许? – texasbruce

+0

@texasbruce我对未来使用异步,但是当你想看到结果时,你需要等到该线程完成。我需要一些信号或事件,以避免等待 – Damir

+0

为什么不从一个产生的线程开始? – texasbruce

回答

5

现行标准 C++中没有明确要做到这一点。

std::future::then()位于标准化管道中,可能包含在C++ 1y或TR中。

有几个支持这个成语的第三方库:

相关:Asio是一个C++异步I/O库,仅支持非阻塞I/O操作,而不支持常规计算操作。 (Node.js的主要用于I/O,所以这可能是足够的。)

否则,你可以推出自己的解决方法:

auto myFuture = std::async([](){ 
    doWork(); 
}).share(); 
auto myNextFuture = std::async([=](){ 
    myFuture.wait(); 
    doMoreWork(); 
}); 

您可以打包这成一个可重用的帮手:

template <typename Future, typename Work> 
auto after(Future f, Work w) -> std::future<decltype(w())> 
{ 
    return std::async([=]() -> decltype(w()) { f.wait(); return w(); }); 
} 

并使用它像这样:

auto myFuture = std::async([](){ 
    doWork(); 
}); 
auto myNextFuture = after(myFuture.share(), [](){ 
    doMoreWork(); 
}); 

通过这种方法,你支付额外的threa成本d(可能)。

相关:C++ Concurrency Herb Sutter的谈话。

+0

记得设置'std :: launch :: deferred'或'std :: launch :: async',这样你就可以完全控制调度。我相信你应该使用'async'。它不如'then()'高效,因为它创建了一个不断阻塞的额外线程(系统资源),并且在它解除阻塞之后,它可能会导致处理器切换,从而失去热缓存。 –

2

std :: future :: then()和Oktalist的continuation实现将会做得很好,如果你真的不需要在主线程中执行回调的话。但是,如果这是一项要求,它们还不够。

如果您有一个事件循环运行(大多数GUI应用程序将有一个),您可以从继续通知循环执行回调。

在Qt中,您可以从延续内部发送信号到生活在主线程中的对象。事件循环将最终在主线程中执行插槽。

如果你没有事件循环升压协程可能是一个选项,但我没有使用它们自己。

1

建立一个任务队列在主线程中运行。将它设置为多作者单读者线程安全(在CS文本或Web上有很多这样的实例)。

队列应该在非空时发出信号,并允许读者等待。

让您的线程将队列中的任务排入队列。使主要的等待它。

如果主线程需要'同时'做其他事情,则将这些任务排入同一个线程。也就是说,如果您对用户输入做出响应,请将用户输入读取线程折腾到代表要处理的用户输入的队列中。

出于重复性原因,线程处理用户输入应该避免复杂的计算。

这种技术被称为'消息泵' - '主'线程服务于消息泵(任务队列),按顺序手动消息每个消息(入队任务)。在工业规模的应用程序中,每次都会发送抽象请求而不是显式任务,并且会发生消息元素处理(回退处理程序等)。

你'在主线程上运行'包含为主线程发出'运行此任务'消息。 “传统”C++程序的主线程不是消息泵,因此注入代码运行是不可行的。大多数gui框架都有一个消息泵系统可以挂接进去。由于javascript是以用户为中心的语言,因此主要的内容就是隐式地提供消息泵之类的东西。

相关问题