2013-06-24 4 views
5
나는 아주 쉽게해야하고 싶지,하지만 나는 그것을 얻지 않는다 무엇

은 ...사용 멤버 함수 :: packaged_task

내가하고 싶은 모두에서 클래스의 멤버 함수를 시작하는 것입니다 배경 특정 시간에 . 그 기능의 결과는 또한 "외부 적으로"이용 가능해야한다. 그래서 생성자에서 작업을 준비하고 (미래 변수 설정, ...) 나중에 나중에 시작하고 싶습니다.

나는 표준 결합을 시도 : | 비동기 | :(packaged_task 미래를)하지만 나는 그것이 작동하지 않았다.

이 조각은 컴파일되지 않습니다,하지만 난 그게 내가하고 싶은 것을 보여줍니다 생각 :

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 = std::async(std::launch::async, task); 
// ^^^^^^^^ 

(*) I : (*)

이 마지막 문제를 해결하기 위해, 당신은 (오히려 result 건설에 std::packaged_task::get_future()에 의해 반환 된 미래를 할당하는 것보다) 당신의 result 멤버 변수에 반환 된 미래를 저장할 수 은 MSVC가이 사양을 무시하고 실제로 비동기 적으로 작업을 실행한다고 생각합니다. 따라서 VS2012로 작업하는 경우이 문제가 발생하지 않을 수 있습니다.

편집 :

As correctly mentioned by Praetorian in his answerpackaged_task의 사본이 async()의 구현 내에서 어떤 점에서 시도 될 수 있기 때문에 위에서 여전히 문제가 될 것입니다. 이 문제를 해결하려면 std::ref()을 사용하여 task 개체를 참조 래퍼에 넣으십시오.

+0

감사합니다. 그거야. 하지만 비동기 적으로 작업을 시작하려면 어떻게해야합니까? std :: async as (std :: launch :: async, task) as 여전히 작동하지 않습니다. – rralf

+1

@rralf : 왜냐하면 (1) 함수를 호출하지 않고 객체를 선언하고 (2) 이상한 블로킹 때문에 반환 된 미래를 사용하지 않을 때'async()'의 동작. 그냥'auto f = async (...)'를해라. 수정 된 답변보기 :) –

+0

마지막 코드 블록이 잘못되었다고 생각합니다. 'as '를 제거하십시오. – 0x499602D2

4

do_something()은 구성원 함수이므로 암시적인 this 포인터를 첫 번째 인수로 사용합니다. this 포인터는 bind 포인터이거나 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));