প্যাকেজড_টাস্ক এবং অ্যাসিঙ্কের মধ্যে পার্থক্য কী


134

সি ++ 11 এর থ্রেডযুক্ত মডেলটির সাথে কাজ করার সময় আমি লক্ষ্য করেছি

std::packaged_task<int(int,int)> task([](int a, int b) { return a + b; });
auto f = task.get_future();
task(2,3);
std::cout << f.get() << '\n';

এবং

auto f = std::async(std::launch::async, 
    [](int a, int b) { return a + b; }, 2, 3);
std::cout << f.get() << '\n';

ঠিক একই জিনিস করতে বলে মনে হচ্ছে। আমি বুঝতে একটি প্রধান পার্থক্য যদি আমি দৌড়ে সেখানে হতে পারে যে std::asyncসঙ্গে std::launch::deferred, কিন্তু এই ক্ষেত্রে সেখানে কেউ নেই?

এই দুটি পদ্ধতির মধ্যে কী পার্থক্য রয়েছে এবং আরও গুরুত্বপূর্ণ, কোন ব্যবহারের ক্ষেত্রে আমার একটির অপরটি ব্যবহার করা উচিত?

উত্তর:


161

প্রকৃতপক্ষে যে উদাহরণটি আপনি সবে দিয়েছেন তার মধ্যে পার্থক্যগুলি দেখায় যদি আপনি একটি দীর্ঘ দীর্ঘ ক্রিয়া ব্যবহার করেন, যেমন

//! sleeps for one second and returns 1
auto sleep = [](){
    std::this_thread::sleep_for(std::chrono::seconds(1));
    return 1;
};

প্যাকেজড টাস্ক

একটি 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সঙ্গে 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;
*/

সুতরাং আপনি যদি সত্যিকারের অ্যাসিঙ্ক্রোনাস চান তবে আপনাকে ফেরত রাখা উচিত future, বা যদি পরিস্থিতি পরিবর্তন হয় তবে আপনি যদি ফলাফলটির জন্য যত্ন নেন না:

{
    auto pizza = std::async(get_pizza);
    /* ... */
    if(need_to_go)
        return;          // ~future will block
    else
       eat(pizza.get());
}   

এই বিষয়ে আরও তথ্যের জন্য, ঔষধি Sutter এর নিবন্ধ দেখুন asyncএবং~future , যা সমস্যা বর্ণনা করে, এবং স্কট মেয়ার এর std::futuresথেকে std::asyncবিশেষ হয় না , যা অর্ন্তদৃষ্টি বর্ণনা করা হয়েছে। এছাড়াও নোট করুন যে এই আচরণটি C ++ 14 এবং তার চেয়ে বেশি ক্ষেত্রে নির্দিষ্ট করা হয়েছিল , তবে সাধারণভাবে C ++ 11 এও প্রয়োগ করা হয়েছে implemented

আরও পার্থক্য

ব্যবহার করে 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);

টি এল; ডিআর

ব্যবহারের std::asyncআপনি কিছু কিছু কাজ এবং সত্যিই পরোয়া করি না যখন তারা কাজ করছি, এবং চান তাহলে std::packaged_taskআপনি তাদের অন্যান্য থ্রেড থেকে সরানো বা তাদের পরে ফোন করার জন্য জিনিষ আপ মোড়ানো চান। বা, খ্রিস্টানকে উদ্ধৃত করতে :

শেষে এ std::packaged_taskবাস্তবায়নের জন্য কেবলমাত্র একটি নিম্ন স্তরের বৈশিষ্ট্য std::async(যার কারণে এটি std::asyncঅন্যান্য নিম্ন স্তরের স্টাফগুলির সাথে একসাথে ব্যবহৃত হলে এর চেয়ে আরও বেশি কিছু করতে পারে , যেমন std::thread)। সহজভাবে কথিত a std::packaged_taskহ'ল একটি std::functionলিঙ্কযুক্ত std::futureএবং std::asyncমোড়কে এবং একটিকে std::packaged_task(সম্ভবত অন্য কোনও থ্রেডে) কল করে।


9
আপনার যুক্ত করা উচিত যে ভবিষ্যতে ধ্বংস হিসাবে অ্যাসিঙ্ক ব্লকগুলি দিয়ে ফিরে আসে (যেমন আপনি বলেছিলেন) যদিও প্যাকেজড_টাস্ক থেকে ফিরে আসাটি তা করে না।
5342

22
শেষে এ std::packaged_taskবাস্তবায়নের জন্য কেবলমাত্র একটি নিম্ন স্তরের বৈশিষ্ট্য std::async(যার কারণে এটি std::asyncঅন্যান্য নিম্ন স্তরের স্টাফগুলির সাথে একসাথে ব্যবহৃত হলে এর চেয়ে আরও বেশি কিছু করতে পারে , যেমন std::thread)। সহজভাবে কথিত a std::packaged_taskহ'ল একটি std::functionলিঙ্কযুক্ত std::futureএবং std::asyncমোড়কে এবং একটিকে std::packaged_task(সম্ভবত অন্য কোনও থ্রেডে) কল করে।
খ্রিস্টান রাউ

আমি ভবিষ্যতের () ব্লকটিতে কিছু পরীক্ষা-নিরীক্ষা করছি। আমি ভবিষ্যতের অবজেক্ট ধ্বংসের উপরে ব্লকিং প্রভাবটি প্রতিলিপি করতে পারিনি। সবকিছু অ্যাসিক্রোনাল দিয়ে কাজ করেছিল। আমি ভিএস 2013 ব্যবহার করছি এবং যখন আমি অ্যাসিঙ্ক চালু করি তখন আমি স্টাডি :: লঞ্চ :: অ্যাসিঙ্ক ব্যবহার করি। ভিসি ++ এই সমস্যাটিকে কোনওভাবে "স্থির" করে?
ফ্র্যাঙ্ক লিউ

1
@ ফ্র্যাঙ্কলিউ: ওয়েল, এন 3451 একটি স্বীকৃত প্রস্তাব, যা (যতদূর আমি জানি) সি ++ 14 এ গেছে। হার্ব মাইক্রোসফ্টে কাজ করে তা দেওয়া, সেই বৈশিষ্ট্যটি ভিএস ২০১৩ সালে প্রয়োগ করা হলে আমি অবাক হব না। একটি সংকলক যা সি ++ 11 বিধি কঠোরভাবে অনুসরণ করে তা এখনও এই আচরণটি দেখায়।
জিটা

1
@ মিখাইল এই উত্তরটি সি ++ ১৪ এবং সি ++ 17 উভয়ের আগেই রয়েছে, সুতরাং আমার কাছে মান ছিল না তবে কেবল হাতে প্রস্তাব ছিল। আমি অনুচ্ছেদটি সরিয়ে ফেলব।
জিটা 21'18

1

প্যাকেজড টাস্ক বনাম অ্যাসিঙ্ক

p> প্যাকেজড টাস্কটি একটি টাস্ক[function or function object]এবং ভবিষ্যত / প্রতিশ্রুতি জোড় রাখে। যখন কাজটি একটি রিটার্ন বিবৃতি কার্যকর করে, তখন এটিতার প্রতিশ্রুতিরকারণset_value(..)হয়packaged_task

a> প্রদত্ত ভবিষ্যত, প্রতিশ্রুতি এবং প্যাকেজ টাস্ক আমরা থ্রেডগুলি সম্পর্কে খুব বেশি চিন্তা না করেই সাধারণ কাজগুলি তৈরি করতে পারি [থ্রেড কেবল কোনও কাজ চালানোর জন্য আমরা দিই] give

তবে আমরা বা বিবেচনা কতগুলি থ্রেড ব্যবহার করতে হবে একটি টাস্ক বর্তমান থ্রেডে বা অন্য etc.Such descisions সেরা রান একটি থ্রেড লঞ্চার নামক দ্বারা পরিচালিত করা যেতে পারে কিনা async(), একটি নতুন একটি থ্রেড তৈরি বা পুরনো জিনিসকে কিনা সিদ্ধান্ত নেয় যে এক বা কেবল বর্তমান থ্রেডে টাস্কটি চালান। এটি ভবিষ্যতের প্রত্যাবর্তন করে।


0

"শ্রেণীর টেমপ্লেট std :: packaged_task কোনও কলযোগ্য লক্ষ্য (ফাংশন, ল্যাম্বডা এক্সপ্রেশন, বাইন্ড এক্সপ্রেশন, বা অন্য কোনও ফাংশন অবজেক্ট) মোড়ন করে যাতে এটি অবিচ্ছিন্নভাবে আহ্বান করা যায় thrown এসটিডি :: ভবিষ্যতের বস্তুগুলির মাধ্যমে।

"টেমপ্লেট ফাংশন অ্যাসিঙ্কটি অ্যাসিনক্রোনাস ফ (ফাংশনটি পৃথক থ্রেডে) চালায় এবং একটি স্ট্যান্ড :: ভবিষ্যত প্রদান করে যা শেষ পর্যন্ত সেই ফাংশন কলটির ফলাফল ধারণ করবে hold"

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.