2009-12-06 94 views
6

我使用asio同步套接字從後臺線程通過TCP讀取數據。這被封裝在一個「服務器」類中。中斷boost :: asio同步讀取?

但是,我希望線程在調用此類的析構函數時退出。 問題是,對任何讀取函數的調用都會阻塞,所以線程不能輕易終止。在Win32中有一個API:WaitForMultipleObjects這將做我想要的。

我該如何達到與提升類似的效果?

回答

2

在我們的應用程序中,我們設置「終止」條件,然後使用線程正在監聽的端口的自連接,以便它醒來,記錄終止條件並終止。

你也可以檢查boost實現 - 如果他們只是在套接字上進行一個簡單的讀操作(即,不在內部使用像WaitForMultipleObjects這樣的東西),那麼你可能會得出結論:沒有任何東西可以簡單幹淨地解除阻塞線程。如果他們在等待多個對象(或一個完成端口),你可以四處挖掘,看看喚醒阻塞線程的能力是否暴露在外。

最後,你可以殺死這個線程 - 但是你必須走出提升之外才能做到這一點,並理解後果,比如懸掛或泄露的資源。如果你正在關閉,這可能不是一個問題,這取決於該線程正在做什麼。

2

我發現沒有簡單的方法來做到這一點。據說,有辦法取消win32 IOCP,但在Windows XP上無法正常工作。 MS確實爲Windows Vista和Windows 7進行了修復。推薦的取消asio async_readasync_write的方法是關閉插槽。

  • [析]注意,我們要拆毀
  • [析]關閉套接字
  • [析]等待完成處理

  • [完成]如果拆了,我們只是失敗因爲套接字關閉,通知析構函數完成處理程序已完成。

  • [完成]立即返回。

如果您選擇實現此目標,請小心。關閉套接字非常簡單。 '等待完成處理程序'然而卻是巨大的下界。當服務器的線程和析構函數進行交互時,可能會出現一些細微的角落情況和競態條件。

這是不夠,我們建立了一個完成的包裝(類似於io_service::strand微妙只是爲了處理同步取消所有未決的完成回調。

1

最好的方法是創建一個socketpair(),(不管它是什麼在boost::asio的說法),加閱讀器結束事件循環,然後關閉書寫器端,您將立即在該插槽上發生eof事件喚醒。

線程必須自動關閉。

線程應在其析構函數,有以下的產卵:

~object() 
{ 
    shutdown_queue.shutdown(); // ask thread to shut down 
    thread.join();    // wait until it does 
} 
-1

使用socket.cancel();結束在套接字上阻塞的所有當前異步操作。客戶端套接字可能需要在循環中被終止。我從來不需要關閉服務器,但是可以使用shared_from_this()並在循環中運行cancel()/ close(),這與增強聊天示例async_如何寫入所有客戶端類似。