2014-04-27 32 views
3

如果我從主線程啓動thread,是否有任何選項可以掛鉤新線程將要觸發的回調。應該在主線程中執行回調。是在c + + 11線程node.js/javascript的回調類似的東西?

在我使用future此任務的時刻,但我想避免等待結果(結果是布爾值,如果true一切正常,萬一false我需要重新開始線程嘗試做任務)。 在C++ 11中類似於node.js/javascript回調的東西嗎?

+0

'std :: async'也許? – texasbruce

+0

@texasbruce我對未來使用異步,但是當你想看到結果時,你需要等到該線程完成。我需要一些信號或事件,以避免等待 – Damir

+0

爲什麼不從一個產生的線程開始? – texasbruce

回答

5

現行標準 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的談話。

+0

記得設置'std :: launch :: deferred'或'std :: launch :: async',這樣你就可以完全控制調度。我相信你應該使用'async'。它不如'then()'高效,因爲它創建了一個不斷阻塞的額外線程(系統資源),並且在它解除阻塞之後,它可能會導致處理器切換,從而失去熱緩存。 –

2

std :: future :: then()和Oktalist的continuation實現將會做得很好,如果你真的不需要在主線程中執行回調的話。但是,如果這是一項要求,它們還不夠。

如果您有一個事件循環運行(大多數GUI應用程序將有一個),您可以從繼續通知循環執行回調。

在Qt中,您可以從延續內部發送信號到生活在主線程中的對象。事件循環將最終在主線程中執行插槽。

如果你沒有事件循環升壓協程可能是一個選項,但我沒有使用它們自己。

1

建立一個任務隊列在主線程中運行。將它設置爲多作者單讀者線程安全(在CS文本或Web上有很多這樣的實例)。

隊列應該在非空時發出信號,並允許讀者等待。

讓您的線程將隊列中的任務排入隊列。使主要的等待它。

如果主線程需要'同時'做其他事情,則將這些任務排入同一個線程。也就是說,如果您對用戶輸入做出響應,請將用戶輸入讀取線程折騰到代表要處理的用戶輸入的隊列中。

出於重複性原因,線程處理用戶輸入應該避免複雜的計算。

這種技術被稱爲'消息泵' - '主'線程服務於消息泵(任務隊列),按順序手動消息每個消息(入隊任務)。在工業規模的應用程序中,每次都會發送抽象請求而不是顯式任務,並且會發生消息元素處理(回退處理程序等)。

你'在主線程上運行'包含爲主線程發出'運行此任務'消息。 「傳統」C++程序的主線程不是消息泵,因此注入代碼運行是不可行的。大多數gui框架都有一個消息泵系統可以掛接進去。由於javascript是以用戶爲中心的語言,因此主要的內容就是隱式地提供消息泵之類的東西。

相關問題