5

問題のあるコードを次のように減らしました。独自のスレッドでメンバー関数を実行するクラス C があります。CI のデストラクタで、このスレッドをきれいに終了したい。これは、c が main 内で定義されている限り (1) 正常に機能しますが、グローバル変数 (2) の場合は機能しません。後者の場合、スレッド関数は返されますが、t.join() がハングすることがわかります。

#include <mutex>
#include <condition_variable>
#include <thread>
#include <iostream>

using namespace std;

class C
{
public:
    C()
    {
        stop = false;
        t = thread(&C::ThreadFunc, this);
    }
    ~C()
    {
        stop = true;
        cv.notify_all();
        if (t.joinable())
        {
            cout << "joining" << endl;
            t.join();
            cout << "joined" << endl;
        }
    }

private:
    void ThreadFunc()
    {
        while (true)
        {
            unique_lock<mutex> lock(m);
            cv.wait(lock, [&]{return stop;});
            cout << "returning" << endl;
            return;
        }
    }

    thread t;
    mutex m;
    condition_variable cv;
    bool stop;
};

C c;  // does *not* work (2)

int _tmain(int argc, _TCHAR* argv[])
{
    C c;  // does work (1)
    return 0;
}

グローバル変数を使用する理由は、それが実際には dll の一部であるためです。DLL_PROCESS_DETACH で DllMain からデストラクタがトリガーされると、同じ問題が発生します。この問題の説明と解決策はありますか?

4

1 に答える 1

4

デッドロックです。t終了を待っている間、終了するために必要なロックを保持していtます。

tのデタッチ プロセスの一部として、DLL を呼び出します。部分的に接続されているスレッド ( を呼び出したスレッド) がある場合、DLL はどのように要求を適切に処理できますjoinか? デタッチを開始すると、デタッチが完了するまで、DLL は一貫性のない状態になり、スレッドのアタッチおよびデタッチ操作を適切に処理できません。

プロセスが制御できないコンテキストにあるときに、スレッドに参加しようとするのは本当に望ましくありません。

于 2013-10-02T20:50:56.550 に答える