C++ 等待但允许事件触发

标签 c++ c++11 winapi signalr concurrency-runtime

使用 Visual Studio 2013 构建 SignalR C++ 客户端,我从 NuGet 包 Microsoft.AspNet.SignalR.Client.Cpp.v120.WinDesktop 中的工作示例代码开始,来源 here

查看库源代码,在我看来,事件处理过程基于 Concurrency Runtime (pplx::task) 依赖 C++11 features

void chat(const utility::string_t& name)
{
    signalr::hub_connection connection{ U("https://testsite") };
    auto proxy = connection.create_hub_proxy(U("ChatHub"));
    proxy.on(U("broadcastMessage"), [](const web::json::value& m)
    {
        ucout << std::endl << m.at(0).as_string() << U(" wrote:") << m.at(1).as_string() << std::endl << U("Enter your message: ");
    });

    connection.start()
        .then([proxy, name]()
    {
        for (;;)
        {
            utility::string_t message;
            std::getline(ucin, message);

            if (message == U(":q"))
            {
                break;
            }

            send_message(proxy, name, message);
        }
    })
        .then([&connection]() // fine to capture by reference - we are blocking so it is guaranteed to be valid
    {
        return connection.stop();
    })
        .then([](pplx::task<void> stop_task)
    {
        try
        {
            stop_task.get();
            ucout << U("connection stopped successfully") << std::endl;
        }
        catch (const std::exception &e)
        {
            ucout << U("exception when starting or stopping connection: ") << e.what() << std::endl;
        }
    }).get();
}

我想消除“用户输入”组件;并在收到特定的“broadcastMessage”时退出循环。

如果我用 sleep 语句替换 for 循环,broadcastMessage 事件将停止触发。

如果我使用不带 getline 的 for 循环,完成后将 bComplete 设置为 true,它会按我想要的方式工作,但会导致 CPU 使用率较高(显然)

for (;;)
{
if (bComplete) break;
}

理想情况下,我希望启动连接,然后等待广播消息事件发出信号以关闭连接。 此外,“聊天”功能在连接关闭之前不应返回。

最佳答案

我可以在 your answer 中看到您已经发现了Windows event objects ;但是,如果您正在寻找独立于 C++11 平台的解决方案,请考虑 std::condition_variable !

unsigned int accountAmount;
std::mutex mx;
std::condition_variable cv;

void depositMoney()
{
    // go to the bank etc...
    // wait in line...
    {
        std::unique_lock<std::mutex> lock(mx);
        std::cout << "Depositing money" << std::endl;
        accountAmount += 5000;
    }
    // Notify others we're finished
    cv.notify_all();
}
void withdrawMoney()
{
    std::unique_lock<std::mutex> lock(mx);
    // Wait until we know the money is there
    cv.wait(lock);
    std::cout << "Withdrawing money" << std::endl;
    accountAmount -= 2000;
}
int main()
{
    accountAmount = 0;
    std::thread deposit(&depositMoney);
    std::thread withdraw(&withdrawMoney);
    deposit.join();
    withdraw.join();
    std::cout << "All transactions processed. Final amount: " << accountAmount << std::endl;
    return 0;
}

在此示例中,我们创建两个线程:一个用于将钱存入帐户,另一个用于取款。因为提款线程可能会先运行,特别是因为 depositMoney() 涉及更多处理,所以我们需要等待,直到知道钱在那里。我们在获取资金之前锁定线程,然后告诉 condition_variable 我们正在等待什么。 condition_variable 将解锁线程,一旦存入资金并调用 notify_all(),我们将被重新唤醒以完成逻辑处理。

请注意,可以使用 Windows event objects 执行完全相同的操作。您可以使用 SetEvent() 代替 std::condition_variable::wait()std::condition_variable::notify_all() WaitForSingleObject()。但这是独立于平台的。

关于C++ 等待但允许事件触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33556145/

相关文章:

winapi - 从 Windows 查询调制解调器获取输出日志

c++ - 在 C++ 中初始化多个类属性的最佳实践

c++ - 底层 std::array 的正确类型

c++ - 整数数组的位封装

c++ - 使用 std::shared_ptr<void> 指向任何东西

c++ - 如何将 unique_ptr 与更通用的删除器一起使用?

windows - 在 Windows 上的软件中关闭 USB 设备

c++ - 无法为进程中的所有线程安装 Hook

php - 为什么我的 php 代码使用 chr 输出的结果与我的 C++ 不同

c# - 识别本地网络上的用户和机器