2013-06-24 92 views
5

我想做的事情應該很容易,但我不明白...在std :: packaged_task中使用成員函數

我想要做的就是啓動一個類的成員函數背景 在某個特定的時間點。該功能的結果也應該是「外部」可用的。所以我想在構造函數中準備任務(設置未來變量,...)並在稍後的時間點啓動它。

我試圖將std :: :(packaged_task | async | future)結合起來,但我沒有得到它的工作。

此段代碼將無法編譯,但我認爲這顯示了我想做的事:

class foo { 
private: 
    // This function shall run in background as a thread 
    // when it gets triggered to start at some certain point 
    bool do_something() { return true; } 

    std::packaged_task<bool()> task; 
    std::future<bool> result; 

public: 
    foo() : 
    task(do_something), // yes, that's wrong, but how to do it right? 
    result(task.get_future()) 
    { 
    // do some initialization stuff 
    ..... 
    } 
    ~foo() {} 

    void start() { 
    // Start Task as asynchron thread 
    std::async as(std::launch::async, task); // Also doesn't work... 
    } 

    // This function should return the result of do_something 
    bool get_result() { return result.get(); } 
}; 

提前感謝!

+0

'std :: async'是一個函數,而不是一個類型 –

回答

8

只需使用std::bind()

#include <functional> // For std::bind() 

foo() : 
    task(std::bind(&foo::do_something, this)), 
//  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
    result(task.get_future()) 
{ 
    // ... 
} 

而且,你在這裏做了錯誤的事情:

std::async as(std::launch::async, task) 
//   ^^ 
//   Trying to declare a variable? 

既然你想要的是調用std::async()功能,不申報的對象(不存在)類型std::async()。當返回的將來被丟棄,因爲的std::async()的古怪行爲,你的任務:但是

std::async(std::launch::async, task) 

注意的是,這會不會是足以讓異步運行任務:那麼作爲第一步,改變這種成將始終執行好像您同步啓動它 - 返回的未來對象的析構函數將阻塞,直到操作完成。 (*)

爲了解決這個最後一個問題,你可以在你result成員變量保存返回的未來(而不是分配給result構造時由std::packaged_task::get_future()回到未來):

result = std::async(std::launch::async, task); 
// ^^^^^^^^ 

(*)我認爲 MSVC忽略此規範並且實際上異步地執行任務。所以如果你使用VS2012,你可能不會遇到這個問題。

編輯:

As correctly mentioned by Praetorian in his answer,上面仍然是有問題的,因爲packaged_task的副本將在async()實施中的一些點嘗試。要解決此問題,請使用std::ref()將您的task對象包裝在引用包裝中。

+0

非常感謝。這樣可行。但是,我如何異步啓動任務? std :: async as(std :: launch :: async,task)仍然不起作用 – rralf

+1

@rralf:這是因爲(1)你聲明瞭一個對象,沒有調用函數,(2)因爲一個奇怪的阻塞當你不使用返回的未來時,'async()'的行爲。只要做'auto f = async(...)'。見編輯答案:) –

+0

我認爲最後的代碼塊是錯誤的。擺脫'as'。 – 0x499602D2

4

do_something()是一個成員函數,這意味着它需要一個隱含的指針this作爲第一個參數。您需要bindthis指針,或者創建一個調用do_something的lamda。

foo() : 
    task(std::bind(&foo::do_something, this)), 
    result(task.get_future()) 
{} 

foo() : 
    task([this]{ return do_something(); }), 
    result(task.get_future()) 
{} 

std::async as(std::launch::async, task); 

std::async是一個函數模板,而不是一個類型。因此,明顯的變化是

std::async(std::launch::async, task); 

但是,這會導致另一個錯誤,因爲地方的那個膽量中調用的task副本嘗試,但std::packaged_task有缺失的拷貝構造函數。你可以通過使用std::ref來解決這個問題,這將避免複製。

std::async(std::launch::async, std::ref(task)); 
相關問題