2014-02-27 30 views
0

我不知道如何處理從Windows控制檯發出的Ctrl-CZeroMQ:如何在Windows上處理Ctrl-C

#include <iostream> 
#include <zmq.hpp> 
#include <windows.h> 

BOOL WINAPI consoleHandler(DWORD dwCtrlType) { 
    // what to do here? 
    return TRUE; 
} 

int main() { 
    SetConsoleCtrlHandler(consoleHandler, TRUE); 

    zmq::context_t context(1); 
    zmq::socket_t socket(context, ZMQ_REP); 
    socket.bind("tcp://*:5555"); 

    while (true) { 
     zmq::message_t request; 
     try { 
      socket.recv(&request); 
     } 
     catch(zmq::error_t& e) { 
      std::cout << "zmq error" << std::endl; 
     } 
    } 
} 

這將安裝一個處理函數,可以在一個CTRL_C_EVENT從控制檯來行事。目前,它什麼都不做。因此,revc調用不會拋出異常as described here (in "Error handling")

我想要做的是break循環在異常處理程序中,並讓C++綁定的RAII功能在退出main()時執行所需的清理。

回答

1

通常我會創建一個標誌或某種排序 - 全局布爾或內核事件。

然後你循環等待這個標誌被重置 - 所以在你的情況下,我會創建一個簡單的全局布爾然後循環它而不是while(true)。

這樣:

bool g_shutdown = false; 

BOOL WINAPI consoleHandler(DWORD dwCtrlType) { 
    g_shutdown = true; 
    return TRUE; 
} 

while (!g_shutdown) 
{ 
// do your zmq work 
} 

它的簡單而有效 - 儘管直到ZMQ下班輪while循環再次檢查這會不會殺了你的計劃。 (你通常可以通過關閉socket變量來實現)

對於一個更強大的(即更快的殺死,取決於你的情況),使用Event和WaitforMultipleObject調用來等待這個關閉事件和其他任何事情程序正在等待(即該套接字的recv調用)。

+0

是的,這就是[zguide示例](http://zguide.zeromq.org/cpp:interrupt)所做的。也許我被「封鎖閱讀會發出一個信號」的評論誤導了。還有一個問題:爲防萬一沒有消息到達我的套接字,我不得不添加一個超時? – mkluwe

+0

如果你在循環中阻塞,總是要添加一個超時值。然後你至少要定期檢查你的循環控件(如果你喜歡這樣的話,可以選擇寫一個「仍然有效」的消息給日誌)。 – gbjbaanb