如果我從主線程啓動thread,是否有任何選項可以掛鉤新線程將要觸發的回調。應該在主線程中執行回調。是在c + + 11線程node.js/javascript的回調類似的東西?
在我使用future此任務的時刻,但我想避免等待結果(結果是布爾值,如果true
一切正常,萬一false
我需要重新開始線程嘗試做任務)。 在C++ 11中類似於node.js/javascript回調的東西嗎?
如果我從主線程啓動thread,是否有任何選項可以掛鉤新線程將要觸發的回調。應該在主線程中執行回調。是在c + + 11線程node.js/javascript的回調類似的東西?
在我使用future此任務的時刻,但我想避免等待結果(結果是布爾值,如果true
一切正常,萬一false
我需要重新開始線程嘗試做任務)。 在C++ 11中類似於node.js/javascript回調的東西嗎?
在現行標準 C++中沒有明確要做到這一點。
std::future::then()
位於標準化管道中,可能包含在C++ 1y或TR中。
有幾個支持這個成語的第三方庫:
相關:Asio是一個C++異步I/O庫,僅支持非阻塞I/O操作,而不支持常規計算操作。 (Node.js的主要用於I/O,所以這可能是足夠的。)
否則,你可以推出自己的解決方法:
auto myFuture = std::async([](){
doWork();
}).share();
auto myNextFuture = std::async([=](){
myFuture.wait();
doMoreWork();
});
您可以打包這成一個可重用的幫手:
template <typename Future, typename Work>
auto after(Future f, Work w) -> std::future<decltype(w())>
{
return std::async([=]() -> decltype(w()) { f.wait(); return w(); });
}
並使用它像這樣:
auto myFuture = std::async([](){
doWork();
});
auto myNextFuture = after(myFuture.share(), [](){
doMoreWork();
});
通過這種方法,你支付額外的threa成本d(可能)。
相關:C++ Concurrency Herb Sutter的談話。
記得設置'std :: launch :: deferred'或'std :: launch :: async',這樣你就可以完全控制調度。我相信你應該使用'async'。它不如'then()'高效,因爲它創建了一個不斷阻塞的額外線程(系統資源),並且在它解除阻塞之後,它可能會導致處理器切換,從而失去熱緩存。 –
std :: future :: then()和Oktalist的continuation實現將會做得很好,如果你真的不需要在主線程中執行回調的話。但是,如果這是一項要求,它們還不夠。
如果您有一個事件循環運行(大多數GUI應用程序將有一個),您可以從繼續通知循環執行回調。
在Qt中,您可以從延續內部發送信號到生活在主線程中的對象。事件循環將最終在主線程中執行插槽。
如果你沒有事件循環升壓協程可能是一個選項,但我沒有使用它們自己。
建立一個任務隊列在主線程中運行。將它設置爲多作者單讀者線程安全(在CS文本或Web上有很多這樣的實例)。
隊列應該在非空時發出信號,並允許讀者等待。
讓您的線程將隊列中的任務排入隊列。使主要的等待它。
如果主線程需要'同時'做其他事情,則將這些任務排入同一個線程。也就是說,如果您對用戶輸入做出響應,請將用戶輸入讀取線程折騰到代表要處理的用戶輸入的隊列中。
出於重複性原因,線程處理用戶輸入應該避免複雜的計算。
這種技術被稱爲'消息泵' - '主'線程服務於消息泵(任務隊列),按順序手動消息每個消息(入隊任務)。在工業規模的應用程序中,每次都會發送抽象請求而不是顯式任務,並且會發生消息元素處理(回退處理程序等)。
你'在主線程上運行'包含爲主線程發出'運行此任務'消息。 「傳統」C++程序的主線程不是消息泵,因此注入代碼運行是不可行的。大多數gui框架都有一個消息泵系統可以掛接進去。由於javascript是以用戶爲中心的語言,因此主要的內容就是隱式地提供消息泵之類的東西。
'std :: async'也許? – texasbruce
@texasbruce我對未來使用異步,但是當你想看到結果時,你需要等到該線程完成。我需要一些信號或事件,以避免等待 – Damir
爲什麼不從一個產生的線程開始? – texasbruce