我将我们的应用程序从Objective-C和Cocoa转移到了C ++。 在Objective-C中,我经常使用Grand Central Dispatch和非常方便的dispatch_async函数。
转到C ++ 11时,我发现std :: async是最接近的等效项。 我正在使用它的Scott Meyers变体,以确保它确实被异步调用:
template<typename F, typename... Ts>
inline auto NLA_async(F&& f, Ts&&... params)
{
return std::async(std::launch::async,
std::forward<F>(f),
std::forward<Ts>(params)...);
}
我了解到,如果未分配返回的future,则该函数实际上不会被异步调用,因为future d'tor将等待异步块完成。
void foo()
{
NLA_async([]{ // run long task async });
// future returned from NLA_async not captured
// -> std::future d'tor waits for block to be finished
}
所以我想我只是将Future分配给一个类成员,以便它在大多数情况下至少是异步调度的(不理想,但是我认为这是一种快速而肮脏的解决方法)。到目前为止,效果很好。
但是我陷入了一个僵局,我还不了解。 看来该块可能同时执行两次,在我看来,这会导致死锁。
您可以在这里看看:
http://coliru.stacked-crooked.com/a/dc4fcbaff370f1b9
谁能解释为什么同时执行两次?
编辑: 在我的特殊情况下,问题是在异步块的末尾,代码锁定了一个互斥锁,执行了一些工作,然后解锁了互斥锁。在这一点上,我们陷入僵局。似乎正在运行的异步块在完成之前就被删除了,因为互斥锁仍处于锁定状态,尽管它不应该这样做(没有return语句或任何可以解释为什么无法解锁互斥锁的东西)。
答案 0 :(得分:0)
两个线程异步运行的问题可能与以下事实有关:创建未来并将其分配给成员变量不会一步就发生。
首先,创建它并启动线程。然后,在等待第一个线程完成时将其分配给成员变量。
感谢无用指出!