2017-02-18 62 views
1

我想多次調用異步方法。一個簡單的例子如下所示:C++中的多個異步調用

size_t counter(std::string &s) 
{ 
    return s.size(); 
} 

void stringCountAccumulator() 
{ 
    std::vector<std::string> foos = {"this", "is", "spartaa"}; 
    size_t total = 0; 
    for (std::string &s : foos) 
    { 
     std::future<size_t> fut = std::async(
      std::launch::async, 
      counter, s); 

     total += fut.get(); 
    } 
    std::cout << "Total: " << total; 
} 

看來,fut.get()會阻止其他將來的調用。我如何在C++中實現這個問題?我需要在一個單獨的線程中調用一個函數。這個函數「返回」一個值。

回答

2
void stringCountAccumulator() 
{ 
    std::vector<std::string> foos = {"this", "is", "spartaa"}; 
    std::vector<std::future<size_t>> calcs; 
    for (auto&& s : foos) { 
    calcs.push_back(std::async(
     std::launch::async, 
     counter, s) 
    ); 
    } 
    std::size_t total = 0; 
    for (auto&& fut:calcs) 
    total += fut.get(); 
    std::cout << "Total: " << total << "\n"; 
} 

.get()阻塞。所以不要阻塞,直到你排隊完成所有任務。

另一種方案是編寫/查找一個線程池,並讓每個任務更新一個可能的原子(或互斥守護)計數器。

有一個完成任務的計數器被守衛(再次,可能是原子)。

有一個承諾(總數),當你完成最後一項任務時(完成最後一項任務)。

從承諾中回報未來。現在,您將擁有一個代表整個線程池的未來,它將計算它們的值並將其相加,並且具有很多併發性。

一些框架,比如微軟的ppl,有一個系統,它爲你做了這樣的事情;您有返回值的任務和組合這些值的函數對象,並從中獲取組合的結果。

1

看一看這個:C++ threads for background loading。這解釋瞭如何獲得完成任務的結果。

+0

謝謝,我會檢查它。沒有任何回調機制?我是否必須檢查任務是否完成? –

+0

是的,您必須手動檢查任務是否完成。 –

1

您還需要聲明StringCountAccumulator()將被異步執行。只有在未來準備好時才調用future :: get()。這裏是一個代碼片段:

std::future<void> stringCountAccumulator() 
{ 
    std::vector<std::string> foos = {"this", "is", "spartaa"}; 
    size_t total = 0; 
    for (std::string &s : foos) 
    { 
     std::future<size_t> fut = std::async(
      std::launch::async, counter, s); 
     while (!fut.is_ready()) ; 
     total += fut.get(); 
    } 
    std::cout << "Total: " << total; 
    } 
+0

這應該會返回一個'future',但返回語句在哪裏? – smac89