[英]boost::asio, threads and synchronization
這與這個問題有些相關,但我想我需要多了解一點。 我一直試圖讓我的頭腦在幾天內完成這項工作(同時處理其他部分),但現在是時候咬緊牙關並獲得多線程了。 另外,我提供的信息比鏈接的問題要多一些。
首先,關於多線程。 因為我一直在測試我的代碼,所以我沒有煩惱任何多線程。 它只是一個控制台應用程序,它啟動與測試服務器的連接,然后處理其他所有內容。 主循環是這樣的:
while(true)
{
Root::instance().performIO(); // calls io_service::runOne();
}
當我編寫我的主應用程序時,我猜這個解決方案是不可接受的(因為它必須在消息循環中調用,盡管可能,當消息隊列阻塞等待消息時會出現問題。你可以更改它,以便消息循環不會阻止,但那不會打破通過屋頂的CPU使用率嗎?)
似乎解決方案是拋出另一個線程。 好的。 但后來我發現當沒有工作要做時, io_service::run()
返回。 那是什么? 那是沒有數據,還是沒有連接? 如果至少存在一個連接,它是否仍然存活? 如果是這樣,那就不是問題了,因為我只需要在第一次連接時啟動一個新線程,如果在沒有任何事情發生時全部停止,我很高興。 我想我對“沒有工作要做”的定義感到困惑。
然后我不得不擔心我的boost線程與我的主GUI線程同步。 所以,我想我的問題是:
boost::asio::post
實現同步,以便稍后在io_service中調用? 今天我會再讀一些,但是從已經做過這件事的人那里得到一個很好的幫助會很棒。 Boost :: asio文檔並不是很好,到目前為止我的大部分工作都是基於一些文檔,一些試驗/錯誤,網上的一些示例代碼。
1)看看io_service :: work 。 只要工作對象存在,io_service :: run就不會返回。 因此,如果您開始清理,請銷毀工作對象,取消所有未完成的操作,例如套接字上的async_read,等待run返回並清理資源。
2)io_service :: post將從運行io_service的線程異步執行給定的處理程序。 回調可用於獲取執行操作的結果。
3)您需要某種形式的消息傳遞系統來通知您的GUI線程新數據。 這里有幾種可能性。
至於你對這個文檔的評論,我的東西Asio是更好的文檔提升庫之一,它帶有明確的例子。
boost::io_service::run()
僅在沒有任何操作時返回,因此沒有異步操作掛起,例如異步接受/連接,異步讀/寫或異步定時器等待。 所以在調用io_service::run()
,首先必須啟動任何異步操作。
我沒有你有控制台或GUI應用程序嗎? 無論如何,多線程看起來像是一種矯枉過正。 您可以將Asio與消息循環結合使用。 如果它是win32 GUI,你可以從你的OnIdle()處理程序調用io_service :: run_one()。 在控制台應用程序的情況下,您可以設置deadline_timer
定期檢查(每200ms?)用戶輸入並使用io_service::run()
。 單線程中的一切都大大簡化了解決方案
1)在客戶端應用程序中使用boost :: asio關於線程並使它們保持活動狀態的最佳實踐方法是什么?
正如文檔所示 ,調用io_service::run
的線程池是最具可伸縮性和最容易實現的。
2)當從主線程寫入套接字到IO線程時,是否使用boost :: asio :: post實現同步,以便稍后在io_service中調用?
您將需要使用strand來保護可由多個線程調用的任何處理程序。 請參閱此答案,因為它可能會對您有所幫助,以及此示例。
3)收到數據后,人們如何將數據恢復到UI線程? 在過去,當我使用完成端口時,我做了一個特殊事件,可以使用:: SendMessage將數據發布回主UI線程。 它不優雅,但它起作用。
當您向io_service
發布異步事件時,如何以boost::function
的形式提供回調? 然后事件的處理程序可以調用回調並使用結果更新UI。
收到數據后,人們如何將數據恢復到UI線程? 在過去,當我使用完成端口時,我做了一個特殊事件,可以使用:: SendMessage將數據發布回主UI線程。 它不優雅,但它起作用
:: PostMessage可能更合適。
除非一切都在一個線程中運行,否則必須使用這些機制將事件安全地發布到UI線程。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.