重複の可能性:
C++: std::thread からの単純な戻り値?
std::thread から戻りコードを取得する方法はありますか? 整数を返す関数があり、スレッドの実行が完了したときに関数からリターン コードを取得できるようにしたいと考えています。
重複の可能性:
C++: std::thread からの単純な戻り値?
std::thread から戻りコードを取得する方法はありますか? 整数を返す関数があり、スレッドの実行が完了したときに関数からリターン コードを取得できるようにしたいと考えています。
いいえ、そのstd::thread
ためではありません。
代わりに、次async
を取得するために使用しますfuture
。
#include <future>
int myfun(double, char, bool);
auto f = std::async(myfun, arg1, arg2, arg3); // f is a std::future<int>
// ...
int res = f.get();
結果の準備ができているかどうかを確認するには、(ゼロ タイムアウトで)のwait_for
メンバー関数を使用できます。f
他の人が示唆しているように、施設は<future>
これに使用できます。しかし、私は答えに反対します
いいえ、あなたはこれを行うことはできません
std::thread
でやりたいことを行う 1 つの方法を次に示しますstd::thread
。それは決して唯一の方法ではありません:
#include <thread>
#include <iostream>
int func(int x)
{
return x+1;
}
int main()
{
int i;
std::thread t([&] {i = func(2);});
t.join();
std::cout << i << '\n';
}
これにより、移植可能な出力が得られます。
3
Kerrek SBは彼の答えは正しいですが、私は別の例を追加することを提案しました(彼が提案したのは答えであるはずなので、ここにあります)。
最近、少なくともVC11ではstd::async
、アプリケーションが終了するまでスレッドのすべてのリソースが解放されないことを発見しました。これにより、メモリリークの誤検知が発生する可能性があります(たとえば、Visual Leak Detectorを使用してそれらを監視している場合)。
ここで、ほとんどの基本的なアプリケーションでは、この回答の残りの部分を見る価値はありませんが、私のようにメモリリークをチェックする必要があり、最後に解放されない静的データのように、誤検知を発生させる余裕がないことを意味します主な機能。それがあなたの場合なら、これは役立つかもしれません。
std::async
デフォルトでは、別のスレッドで実行されることが保証されていませんstd::launch::async
。これは、最初のパラメーターとして使用する場合のみです。それ以外の場合、実装は何をするかを決定します。そのため、VC11実装は、新しいMicrosoft Concurrency Runtimeタスクマネージャーを使用して、提供された関数をタスクプールにプッシュされたタスクとして管理します。つまり、スレッドは透過的な方法で維持および管理されます。タスクマネージャーを明示的に終了する方法はありますが、プラットフォーム固有であるため、1)スレッドを起動し、2)後で結果を取得し、3)スレッドが完全に解放されたときに、非同期を選択するのは適切ではありません。結果が得られます。
それを正確に行う代替手段は、を使用std::packaged_task
しstd::thread
て組み合わせることstd::future
です。それが行われる方法は、を使用するのとほとんど同じですがstd::async
、もう少し冗長です(つまり、必要に応じてカスタムテンプレート関数で一般化できます)。
#include <packaged_task>
#include <thread>
int myfun(double, char, bool);
std::packaged_task<int(double, char, bool)> task(myfun, arg1, arg2, arg3);
auto f = task.get_future(); // f is a std::future<int>
std::promise
まず、タスクを作成します。基本的には、関数と将来に関連付けられる関数の両方を含むオブジェクトです。std::packaged_task
ほとんどの場合、拡張バージョンのように機能しstd::function
ます。
次に、スレッドを明示的に実行する必要があります。
std::thread thread(std::move(task));
thread.detach();
std::packaged_task
コピーできないため、移動が必要です。スレッドの切り離しは、futureを使用して同期する場合にのみ必要です。それ以外の場合は、スレッドを明示的に結合する必要があります。そうしないと、スレッドのデストラクタが呼び出されたときに、が呼び出されますstd::terminate()
。
// ...
int res = f.get(); // Synchronization and retrieval.
を使用した例を次に示しpackaged_task
ます。
#include <future>
#include <iostream>
void task_waiter(std::future<int>&& f) {
std::future<int> ft = std::move(f);
int result = ft.get();
std::cout << result << '\n';
}
int the_task() {
return 17;
}
int main() {
std::packaged_task<int()> task(the_task);
std::thread thr(task_waiter, task.get_future());
task();
thr.join();
return 0;
}