【问题标题】:How to call a static method asynchronously in c++? [closed]如何在 C++ 中异步调用静态方法? [关闭]
【发布时间】:2020-05-05 03:09:47
【问题描述】:

我想异步运行我的 minimax 算法,这样它就不会在等待转弯时冻结 ui。这是我需要调用的静态方法:

//ChessContext is the current state of the board
//Turn contains fromX, fromY, toX, toY when moving a piece
static Turn getBestTurn(ChessContext cc, int depth);

我试过这个:

//context is a reference to the game currently played
auto fu = std::async(std::launch::async, ChessContext::getBestTurn, context , 5);
Turn t = fu.get();

这给了我一个错误提示

boardview.cpp:69:23: error: no matching function for call to 'async' 
future:1712:5: note: candidate template ignored: substitution failure [with _Fn = Turn (&)(ChessContext, int), _Args = <ChessContext &, int>]:
    no type named 'type' in 'std::result_of<Turn ((ChessContext, int))(ChessContext, int)>'
future:1745:5: note: candidate template ignored: substitution failure [with _Fn = std::launch, _Args = <Turn (&)(ChessContext, int), ChessContext &, int>]:
    no type named 'type' in 'std::result_of<std::launch (Turn ()(ChessContext, int), ChessContext, int)>'

我最终希望在每个可能的情况下都在单独的线程上运行该算法,或者一次在两个线程上运行该算法,看看它是否能给我带来性能提升。

最少的代码:

#include <iostream>
#include <thread>
#include <future> 

class Turn
{
};
class ChessContext 
{
public:
    ChessContext();
    ChessContext(ChessContext &cc);

    static Turn getBestTurn(ChessContext cc, int depth);
}; 

int main(){
    ChessContext context;
    auto fu = std::async(std::launch::async, ChessContext::getBestTurn, context, 5);
}

这是完整的项目 https://github.com/zlatkovnik/Super-Chesster.git

【问题讨论】:

标签: c++ multithreading asynchronous future


【解决方案1】:

您的最小示例编译良好。

您的actual 代码还有这个:

    ChessContext(ChessContext &cc);

这不是一个普通的复制构造函数。复制构造函数 usually 通过 const 引用获取参数。

这是重现您的问题的最小示例:

#include <future>

struct A {
    A() {}
    A(A&) {}
};

void test(A) {}

int main() {
    A a;
    test(a); // OK
    std::async(std::launch::async, &test, a); // Not OK
}

这是因为std::launch::async 复制了参数,并且非常量引用不绑定到临时对象。

要修复,请将复制构造函数更改为

    ChessContext(ChessContext const &cc);

【讨论】:

  • 当我像这样正常运行代码时,代码可以工作: Turn turn = ChessContext::getBestTurn(context, 5); context.playTurn(转);
  • 没注意到,非常感谢!
【解决方案2】:

ChessContext 不可复制。 ChessContext(ChessContext &amp;cc) 不是拷贝构造函数,你需要ChessContext(const ChessContext &amp;cc)

【讨论】:

  • 没注意到,非常感谢!
【解决方案3】:

您可以在这里使用 lambda 让生活更轻松:

auto fu = std::async(std::launch::async, [&]() { ChessContext::getBestTurn(context , 5); });

至于多线程,极小值的工作线程是可取的,但在实际场景中,因为您将需要哈希表和其他东西,以允许强制移动或撤消移动等,不建议为每个深度搜索单独线程。

【讨论】:

  • 现在这条线很好,但它在 fu.get(); 上给了我这个错误; boardview.cpp:70:18:错误:没有从“void”到“Turn”的可行转换 turn.h:13:5:注意:候选构造函数不可行:无法将不完整类型“void”的参数转换为“const Turn & ' 第一个参数
  • 这需要在 lambda 中返回,无论如何都不太可能解决问题
  • 你需要在调用fu.get()之前检查fu是否准备好了
  • 无论如何,在这里使用 std::future 对你没有帮助,因为它会阻塞主 UI 线程,考虑使用其他可行的选项,如 std::atomic 或 std::conditional_variable std::mutex
猜你喜欢
  • 2011-04-18
  • 1970-01-01
  • 1970-01-01
  • 2020-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多