C++等待bool在另一个类中更改

C++ Wait for bool to change in another class

本文关键字:另一个 等待 bool C++      更新时间:2023-10-16

我有一个Program类和一个Browser类。

在我的程序::Run()中,我启动浏览器以在一个单独的线程中启动。然而,在我继续使用Run()方法之前,我想等待浏览器的某个部分初始化,因此我需要检查浏览器对象中是否设置了变量。

用作浏览器的线程

int Program::_Thread_UI_Run() {
  ...
  return Browser->Run();
}

我使用async来运行浏览器线程,并在它完成时检索它的返回值。

int Program::Start() {
    std::unique_lock<std::mutex> lck(mtx);
    auto t1 = std::async(&Program::_Thread_Browser_Run, this);
    cv.wait(lck);
     ... when wait is released, do stuff
    // Thread finishes and returns an exit code for the program
    auto res1 = f1.get();
// return res1 as exit code.
}

浏览器.cpp类

int Browser::Run()
{
    // Initialize many things
    ...
    m_Running = true; 
    cv.notify_all(); // Notify the waiter back in Program
    // This will run for as long as the program is running
    while (m_Running)
    {
      ... browser window message loop
    }
    return exit_code;
}

我在设置时遇到问题。程序正在崩溃:/我是否将互斥变量传递给所有使用它的对象?或者只是在每个功能体中重新创建它?conditional_variable怎么样?

在当前设置中,程序崩溃:异常断点已到达断点。(0x80000003)发生在位置0x107d07d6的应用程序中。

感谢提示和帮助

编辑:更新代码以匹配新建议

在浏览器的.h文件中:std::atomic_bool m_Running;

int Browser::Run(std::condition_variable& cv)
{
    int exit_code = 0;
    // Set up, and attain the desired state:
    ...
    m_Running = true;
    cv.notify_all();
    while (m_Running)
    {
        // Process things etc
    }
    return exit_code;
}
int Program::Start()
{
    std::mutex m;
    std::condition_variable cv;
    auto t1 = std::async(&Program::_Thread_UI_Run, this, std::ref(cv));
    std::unique_lock<std::mutex> lock(m);
    cv.wait(lock);

    .... stuff

    return t1.get();
}

我有一个记录器,可以帮助我跟踪程序的运行情况。通过在代码的关键位置放置记录器调用,我能够确认程序在继续之前等待了适当的时间。然而,我仍然会收到的提示

异常断点已到达断点。(0x80000003)在位置0x107d07d6的应用程序中发生。

通过注释//cv.wait(lock);,程序继续工作。:/为什么要等着让它那样崩溃?

您肯定想要使用std::condition_variable。它允许您在操作完成后向其他线程发出信号,因此在您的情况下,一旦设置了bool

Browser::Run()
{
    // Set some things up, make sure everything is okay:
    ...
    m_Running = true; // Now the thread is, by our standards, running*
    // Let other threads know:
    cv.notify_all();
    // Continue to process thread:
    while (m_Running)
    {
    }
}

然后在你的主/其他线程中:

auto t1 = std::async(&Program::_Thread_Browser_Run, this);
// Wait until we know the thread is actually running. This will pause this thread indefinitely until the condition_variable signals.
cv.wait();

您应该将std::condition_variable传递给任何使用它的函数,这样您的代码看起来更像:

int Browser::Run(std::condition_variable& cv)
{
    int exit_code = 0;
    // Set up, and attain the desired state:
    ...
    m_Running = true;
    cv.notify_all();
    while (m_Running)
    {
        // Process things etc
    }
    return exit_code;
}
int Program::Start()
{
    std::mutex m;
    std::condition_variable cv;
    auto t1 = std::async(&Program::_Thread_UI_Run, this, std::ref(cv));
    std::unique_lock<std::mutex> lock(m);
    // Wait until the browser is in the desired state
    cv.wait(lock);
    // The thread has signalled. At this point, Browser::m_Running = true
    // Wait for the browser to exit, and then propagate its exit code
    return t1.get();
}

@Richard Hodges在评论中提出了一个很好的观点,但我忽略了这一点:m_Running需要是std::atomic(或者在使用时有锁定),否则两个线程可能都会尝试使用一次。std::condition_variable是线程安全的,不需要锁定。

*当然,线程此时正在运行,我只是说它处于您想要的状态