2015-11-05 62 views
1

建立使用Visual Studio 2013 SignalR C++客户端,我开始从NuGet包工作样例代码Microsoft.AspNet.SignalR.Client.Cpp.v120.WinDesktop,源hereC++等来的却允许事件火

审查在我看来,这依赖于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(); 
} 

我想消除“用户输入”组件库的源事件处理过程是基于Concurrency Runtime(pplx ::任务);并且在收到特定的“broadcastMessage”时退出循环。

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

如果我使用for循环没有,则对getline,设置bComplete真做的时候,它的工作就是我想要的,但会导致CPU占用率过高(显然)

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

理想我想连接到开始,然后等待broadcastMessage事件发出信号以关闭连接。 此外,“聊天”功能在连接关闭之前不应返回。

+0

请问您可以添加一些合理的标签,缩小您的问题的背景?这远远超出了C++标准。 –

+0

好吧,我没有意识到这一点,我研究了一些图书馆,并添加了额外的信息/标签。 –

回答

3

我可以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可以完全相同。而不是std::condition_variable::wait()std::condition_variable::notify_all()你会使用SetEvent()WaitForSingleObject()。不过这与平台无关。

0

我得到这个工作使用WinAPI的WaitForSingleObject的:

HANDLE hEvent; 
    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; 
     if (m.at(1).as_string() == L"quit") 
      { 
       SetEvent(hEvent); 
      } 
     }); 

    hEvent = CreateEvent(0, TRUE, FALSE, 0); 

     connection.start() 
      .then([proxy, name]() 
     { 
      WaitForSingleObject(hEvent, INFINITE); 
     }) 
      .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; 
      }`enter code here` 
     }).get(); 
    }