C ++ std :: async调用类成员方法看不到变量

时间:2014-09-12 12:59:43

标签: c++ multithreading c++11 stdasync

我遇到了std :: async正在启动的进程的一些问题。

class BaseClass {
public:
    BaseClass() {enabledFlag = false;}
    virtual ~BaseClass() {}

protected:
    int process();
    bool enabledFlag;
};


int BaseClass::process() {
    int rc = -1;
    if (enabledFlag == false) {
      std::cout << "Not enabled\n" << std::flush;
      return rc;
    }

    rc = 0;
    while (enabledFlag) {
      // this loop should set rc to be something other than zero if an error is to be signalled
      // otherwise loop here doing stuff until the user sets enabledFlag=false
    }

    return rc;
}

class DerivedClassWithExposedMembersForTesting : public BaseClass {
public:
  using BaseClass::enabledFlag;
  using BaseClass::process;

};

在我的Google测试中:

TEST(FixtureName, process_exitsWithRC0_WhenEnabledFlagSetTrueDuringExecution {
    DerivedClassWithExposedMembersForTesting testClass;
    testClass.enabledFlag = true;

    // print status
    std::cout << "Enabled: " <<  testClass.enabledFlag << std::endl << std::flush;

    std::future<int> returnCodeFuture = std::async(std::launch::async, &DerivedClassWithExposedMembersForTesting::process, &testClass);  // starts background execution
    // set flag to false to kill loop
    testClass.enabledFlag = false;

    int rc = returnCodeFuture.get();

    EXPECT_EQ(0, rc);
}

我对std :: async的理解是它应该被调度在调用异步后不久运行,并且如果线程还没有完成,则执行的主线程将在get()调用时阻塞。对get()的调用将返回process()的返回值。

如果未启用testClass,

process()设置为不运行,因此我在测试中启用它。

我希望看到:

Enabled: 1
// test passes

我看到的是:

Enabled: 1
Not enabled
// test fails
Failure
Value of: rc
  Actual: -1
  Expected: 0

为什么std :: async触发的进程没有看到在进行异步调用之前由主进程设置的enabledFlag的值?

注意:enabledFlag应该从外部进程设置,通常不在循环内设置,因此这种结构

**更新** 根据我的评论,我通过在调用async()之后将以下行添加到测试中来修复它:

// Use wait_for() with zero milliseconds to check thread status; delay until it has started
while (returnCodeFuture.wait_for(std::chrono::milliseconds(0)) == std::future_status::deferred) {}

1 个答案:

答案 0 :(得分:1)

问题是,当线程运行时,您不知道。可能是您在线程实际运行之前将标志设置为false

解决此问题的一种简单方法是使用另一个状态变量isRunning,该线程在循环内设置。您的主线程可以检查此线程以了解线程何时运行,然后告诉它结束。