실제로 방금 제공 한 예는 다음과 같이 다소 긴 기능을 사용하면 차이점을 보여줍니다.
//! sleeps for one second and returns 1
auto sleep = [](){
std::this_thread::sleep_for(std::chrono::seconds(1));
return 1;
};
패키지 된 작업
A packaged_task
는 자체적으로 시작되지 않으므로 호출해야합니다.
std::packaged_task<int()> task(sleep);
auto f = task.get_future();
task(); // invoke the function
// You have to wait until task returns. Since task calls sleep
// you will have to wait at least 1 second.
std::cout << "You can see this after 1 second\n";
// However, f.get() will be available, since task has already finished.
std::cout << f.get() << std::endl;
std::async
반면 std::async
with launch::async
는 다른 스레드에서 작업을 실행하려고 시도합니다.
auto f = std::async(std::launch::async, sleep);
std::cout << "You can see this immediately!\n";
// However, the value of the future will be available after sleep has finished
// so f.get() can block up to 1 second.
std::cout << f.get() << "This will be shown after a second!\n";
약점
그러나 async
모든 것을 사용하기 전에 반환 된 미래에는 특별한 공유 상태가 있으므로 future::~future
차단 해야 합니다.
std::async(do_work1); // ~future blocks
std::async(do_work2); // ~future blocks
/* output: (assuming that do_work* log their progress)
do_work1() started;
do_work1() stopped;
do_work2() started;
do_work2() stopped;
*/
따라서 실제 비동기식을 원한다면 return을 유지해야 future
하거나 상황이 바뀌면 결과를 신경 쓰지 않아야합니다.
{
auto pizza = std::async(get_pizza);
/* ... */
if(need_to_go)
return; // ~future will block
else
eat(pizza.get());
}
이에 대한 자세한 내용은 허브 셔터의 문서를 참조 async
하고~future
, 문제를 설명하고, 스콧 마이어의 std::futures
에서이 std::async
특별하지 않은 통찰력을 설명한다. 또한이 동작 은 C ++ 14 이상에서 지정 되었지만 일반적으로 C ++ 11에서도 구현되었습니다.
추가 차이점
사용 std::async
하면 더 이상 특정 스레드에서 작업을 실행할 수 없으며 std::packaged_task
다른 스레드로 이동할 수 있습니다.
std::packaged_task<int(int,int)> task(...);
auto f = task.get_future();
std::thread myThread(std::move(task),2,3);
std::cout << f.get() << "\n";
또한을 packaged_task
호출하기 전에 호출해야합니다 f.get()
. 그렇지 않으면 미래가 준비되지 않으므로 프로그램이 정지됩니다.
std::packaged_task<int(int,int)> task(...);
auto f = task.get_future();
std::cout << f.get() << "\n"; // oops!
task(2,3);
TL; DR
사용 std::async
당신이 어떤 일을 수행하고 완료 할 때 정말 상관하지 않으며, 원하는 경우 std::packaged_task
다른 스레드로 이동하거나 나중에 전화를하기 위해 일을 마무리하려는 경우. 또는 기독교인 을 인용하자면 :
결국 a std::packaged_task
는 구현을위한 저급 기능 일뿐 std::async
입니다 (그래서 std::async
와 같이 다른 저급 물건과 함께 사용하는 것보다 더 많은 일을 할 수있는 이유입니다 std::thread
). 간단하게 음성 A는 std::packaged_task
A는 std::function
A를 연결 std::future
하고 std::async
랩과 호출 std::packaged_task
(아마도 다른 스레드에서).