1. ホーム
  2. c++

[解決済み] std::スレッドがまだ実行されているかどうかを確認するには?

2023-01-10 21:57:31

質問

を確認するにはどうしたらよいでしょうか。 std::thread がまだ実行されているかどうかを (プラットフォームに依存しない方法で) チェックするにはどうしたらよいでしょうか? それは timed_join() メソッドと joinable() はそのためのものではありません。

でmutexをロックすることを考えたのですが、これは std::lock_guard でロックし、スレッド内で try_lock() メソッドを使用して、それがまだロックされているかどうか(スレッドは実行されている)を判断しますが、私には不必要に複雑に思えます。

もっとエレガントな方法をご存知ですか?

更新しました。 明確にするために:私はスレッドがきれいに終了したかどうかをチェックしたいです。ぶら下がった」スレッドはこの目的のために実行されているとみなされます。

どのように解決するのですか?

C++11を利用する場合 std::asyncstd::future を使えば、タスクの実行のために wait_for の機能を利用できます。 std::future を使って、このようにきちんとスレッドがまだ動いているかどうかをチェックします。

#include <future>
#include <thread>
#include <chrono>
#include <iostream>

int main() {
    using namespace std::chrono_literals;

    /* Run some task on new thread. The launch policy std::launch::async
       makes sure that the task is run asynchronously on a new thread. */
    auto future = std::async(std::launch::async, [] {
        std::this_thread::sleep_for(3s);
        return 8;
    });

    // Use wait_for() with zero milliseconds to check thread status.
    auto status = future.wait_for(0ms);

    // Print status.
    if (status == std::future_status::ready) {
        std::cout << "Thread finished" << std::endl;
    } else {
        std::cout << "Thread still running" << std::endl;
    }

    auto result = future.get(); // Get result.
}

もし、どうしても std::thread を使うのであれば std::promise を使って未来のオブジェクトを取得します。

#include <future>
#include <thread>
#include <chrono>
#include <iostream>

int main() {
    using namespace std::chrono_literals;

    // Create a promise and get its future.
    std::promise<bool> p;
    auto future = p.get_future();

    // Run some task on a new thread.
    std::thread t([&p] {
        std::this_thread::sleep_for(3s);
        p.set_value(true); // Is done atomically.
    });

    // Get thread status using wait_for as before.
    auto status = future.wait_for(0ms);

    // Print status.
    if (status == std::future_status::ready) {
        std::cout << "Thread finished" << std::endl;
    } else {
        std::cout << "Thread still running" << std::endl;
    }

    t.join(); // Join thread.
}

これらの例はどちらも出力されます。

Thread still running

これはもちろん、タスクが終了する前にスレッドの状態がチェックされるからです。

しかしまた、他の人がすでに述べたように、ただそれを行う方がよりシンプルかもしれません。

#include <thread>
#include <atomic>
#include <chrono>
#include <iostream>

int main() {
    using namespace std::chrono_literals;

    std::atomic<bool> done(false); // Use an atomic flag.

    /* Run some task on a new thread.
       Make sure to set the done flag to true when finished. */
    std::thread t([&done] {
        std::this_thread::sleep_for(3s);
        done = true;
    });

    // Print status.
    if (done) {
        std::cout << "Thread finished" << std::endl;
    } else {
        std::cout << "Thread still running" << std::endl;
    }

    t.join(); // Join thread.
}

編集します。

また std::packaged_task と一緒に使うために std::thread を使用するよりも、よりクリーンなソリューションです。 std::promise :

#include <future>
#include <thread>
#include <chrono>
#include <iostream>

int main() {
    using namespace std::chrono_literals;

    // Create a packaged_task using some task and get its future.
    std::packaged_task<void()> task([] {
        std::this_thread::sleep_for(3s);
    });
    auto future = task.get_future();

    // Run task on new thread.
    std::thread t(std::move(task));

    // Get thread status using wait_for as before.
    auto status = future.wait_for(0ms);

    // Print status.
    if (status == std::future_status::ready) {
        // ...
    }

    t.join(); // Join thread.
}