1

現在、ブースト スレッドを使用する DLL を作成しています。boost::thread::interrupt() の使用と thread_interrupted 例外のキャッチに問題がありました。一部の割り込みポイントでは、割り込みがスローされてスレッドでキャッチされ、他の割り込みポイントでは、thread.interrupt() が呼び出された場所で割り込みがスローされます。なぜこれが起こるのですか?私の要点を説明するために基本的な例を書きました。それはこの投稿の最後にあります

プログラムは、それぞれ異なる中断ポイントを持つワーカー関数の 1 つを使用するスレッドを開始します。ユーザーが Enter キーを押すと、スレッドが中断され、プログラムが終了します。出力される各ステートメントの前に、スレッド ID が出力されるので、何が起こっているかがわかります。

私は次のようなものを期待しています:

13c4 main thread

790 worker thread
790 thread iteration 1 Press Enter to stop
790 thread iteration 2 Press Enter to stop
790 thread iteration 3 Press Enter to stop
790 Thread is stopped in ThreadFunction
13c4 main: thread ended

Process returned 0 (0x0)   execution time : 0.200 s
Press any key to continue.

ワーカー スレッドと並行して、メイン スレッドが実行されます。ユーザーが Enter キーを押すと、メイン スレッドで割り込みが呼び出されますが、ワーカー スレッドでキャッチされます。その後、スレッドは破棄されます。その後、メイン スレッドが続行され、プログラムが終了します。

私が試したすべての割り込みポイント (interruption_point() を除く) で見られるのは、割り込みがメイン スレッドでキャッチされ、メイン スレッドの実行を継続するワーカー スレッドであるかのように見えることです。そのようです:

1364 main thread
964 worker thread
964 thread iteration 1 Press Enter to stop
964 thread iteration 2 Press Enter to stop
964 thread iteration 3 Press Enter to stop

964 Thread is joined
964 main: thread ended

Process returned 0 (0x0)   execution time : 1.510 s
Press any key to continue.

これは何が原因ですか?たとえば、条件変数を使用するときにワーカー関数で割り込みをキャッチするにはどうすればよいですか? 私はどこかで間違いを犯しましたか?

私のコード:

#define BOOST_THREAD_USE_LIB 1
#define BOOST_SYSTEM_NO_DEPRECATED 1
#define _WIN32_WINNT 0x0501
#define WINVER 0x0501

#include <boost/thread.hpp>
#include <iostream>

using namespace std;

void ThreadFunctionSleep()
{
    cout <<  boost::this_thread::get_id() << " worker thread " << endl;
    int counter = 0;

    while(1)
    {
        cout <<  boost::this_thread::get_id() << " thread iteration " << ++counter << " Press Enter to stop" << endl;

        try
        {
            boost::this_thread::sleep(boost::posix_time::milliseconds(5000));
        }
        catch(boost::thread_interrupted&)
        {
            cout <<  boost::this_thread::get_id() << " Thread is stopped in ThreadFunction " << endl;
            return;
        }

    }




}

void ThreadFunctionSleep2()
{
    cout <<  boost::this_thread::get_id() << " worker thread " << endl;
    int counter = 0;

    try
    {
        cout <<  boost::this_thread::get_id() << " thread iteration " << ++counter << " Press Enter to stop" << endl;

        while(1)
        {
            boost::this_thread::sleep(boost::posix_time::milliseconds(5000));
        }

    }
    catch(boost::thread_interrupted&)
    {
        cout <<  boost::this_thread::get_id() << " Thread is stopped in ThreadFunction " << endl;
        return;
    }





}

void ThreadFunctionInterruptionPoint()
{
    cout <<  boost::this_thread::get_id() << " worker thread " << endl;
    int counter = 0;

    while(1)
    {
        cout <<  boost::this_thread::get_id() << " thread iteration " << ++counter << " Press Enter to stop" << endl;

        try
        {

            boost::this_thread::interruption_point();

        }
        catch(boost::thread_interrupted&)
        {
            cout <<  boost::this_thread::get_id() << " Thread is stopped in ThreadFunction " << endl;
            return;
        }

    }

}

bool myPredicate()
{
    return false;
}

boost::condition_variable full;
boost::condition_variable empty;
boost::mutex fullMut;
boost::mutex emptyMut;

void waitedConditionVariable()
{


    try
    {
        while(1)
        {
            boost::system_time const timeout=boost::get_system_time()+ boost::posix_time::milliseconds(1000);
            boost::unique_lock<boost::mutex> lock(fullMut);
            std::cout << boost::this_thread::get_id()<< "  waiting for condition variable or for timeout" << std::endl;


            if (full.timed_wait(lock, timeout, myPredicate))
            {


                std::cout << boost::this_thread::get_id()<< "  condition variable signalled " << std::endl;

            }
            else
            {
                std::cout << boost::this_thread::get_id()<< " condition variable  timeout. "  << std::endl;

            }



        }
    }
    catch(boost::thread_interrupted & )
    {
        std::cout<< boost::this_thread::get_id() << " waitedConditionVariable thread_interrupted " << std::endl;
        return;

    }
    catch (std::exception& e)
    {

        std::cerr << boost::this_thread::get_id()<< " waitedConditionVariable Thread "
                  << " caught std::exception" << e.what() << std::endl;
                  return;

    }
    catch(...)
    {
        std::cout<< boost::this_thread::get_id() << " waitedConditionVariable other" << std::endl;
        return;

    }

}

void waitedConditionVariable2()
{



    while(1)
    {
        try
        {
            boost::system_time const timeout=boost::get_system_time()+ boost::posix_time::milliseconds(1000);
            boost::unique_lock<boost::mutex> lock(fullMut);
            std::cout << boost::this_thread::get_id()<< "  waiting for condition variable or for timeout" << std::endl;


            if (full.timed_wait(lock, timeout, myPredicate))
            {


                std::cout << boost::this_thread::get_id()<< "  condition variable signalled " << std::endl;

            }
            else
            {
                std::cout << boost::this_thread::get_id()<< " condition variable  timeout. "  << std::endl;

            }



        }
        catch(boost::thread_interrupted & )
        {
            std::cout<< boost::this_thread::get_id() << " waitedConditionVariable thread_interrupted " << std::endl;
            return;

        }
        catch (std::exception& e)
        {

            std::cerr << boost::this_thread::get_id()<< " waitedConditionVariable Thread "
                      << " caught std::exception" << e.what() << std::endl;
            return;

        }
        catch(...)
        {
            std::cout<< boost::this_thread::get_id() << " waitedConditionVariable other" << std::endl;
            return;

        }
    }


}

void normalConditionVariable()
{

    try
    {
        boost::unique_lock<boost::mutex> lock(fullMut);
        while(1)
        {


            std::cout << boost::this_thread::get_id()<< " waiting for condition variable " << std::endl;
            full.wait(lock);

            std::cout << boost::this_thread::get_id()<< " wait done "  << std::endl;

        }
    }
    catch(boost::thread_interrupted & )
    {
        std::cout<< boost::this_thread::get_id() << " normalConditionVariable thread_interrupted " << std::endl;
        return;

    }
    catch (std::exception& e)
    {

        std::cerr << boost::this_thread::get_id()<< " normalConditionVariable Thread "
                  << " caught std::exception" << e.what() << std::endl;
        return;

    }
    catch(...)
    {
        std::cout<< boost::this_thread::get_id() << " normalConditionVariable other" << std::endl;
        return;

    }
}

void normalConditionVariable2()
{

    while(1)
    {
        boost::unique_lock<boost::mutex> lock(fullMut);
        try
        {


            std::cout << boost::this_thread::get_id()<< " waiting for condition variable " << std::endl;
            full.wait(lock);

            std::cout << boost::this_thread::get_id()<< " wait done "  << std::endl;

        }
        catch(boost::thread_interrupted & )
        {
            std::cout<< boost::this_thread::get_id() << " normalConditionVariable thread_interrupted " << std::endl;
            return;

        }
        catch (std::exception& e)
        {

            std::cerr << boost::this_thread::get_id()<< " normalConditionVariable Thread "
                      << " caught std::exception" << e.what() << std::endl;
            return;

        }
        catch(...)
        {
            std::cout<< boost::this_thread::get_id() << " normalConditionVariable other" << std::endl;
            return;

        }
    }

}



int main()
{
    cout <<  boost::this_thread::get_id() << " main thread " << endl;
    // Start thread
    //use thes functions:
    // ThreadFunctionSleep
    // ThreadFunctionSleep2
    //ThreadFunctionInterruptionPoint
    //ThreadFunctionInterruptionPoint2
    // waitedConditionVariable
    // waitedConditionVariable2
    // normalConditionVariable
    // normalConditionVariable2
    boost::thread t(&waitedConditionVariable2);


    // Wait for Enter
    char ch;
    cin.get(ch);

    // Ask thread to stop
    try
    {
        t.interrupt();
    }
    catch(boost::thread_interrupted&)
    {
        cout <<  boost::this_thread::get_id() << " Thread is stopped" << endl;

    }

    // Join - wait when thread actually exits
    try
    {
        t.join();
    }
    catch(boost::thread_interrupted&)
    {
        cout <<  boost::this_thread::get_id() << " Thread is joined" << endl;

    }
    catch(...){
        cout <<  boost::this_thread::get_id() << " other exception" << endl;

    }

    cout <<  boost::this_thread::get_id() << " main: thread ended" << endl;




    return 0;
}

ブースト 1.53.0 と MinGW 4.4.1 を使用しています。boost::thread と boost::system に runtime-link-static マルチスレッド ライブラリを使用しています。

ご協力いただきありがとうございます

4

1 に答える 1

0

例外を再スローする必要boost::threadがあります。そうしないと、実際には中断されません。

以下のコードを試してください。また、さまざまな位置を試しjoin()て、スレッドの状態を示すさまざまな出力を確認できます。

#include <iostream>
#include <boost/thread.hpp>

void foo()
{
    while(true) try
    {
        boost::this_thread::sleep_for(boost::chrono::milliseconds(1000));
        std::cout << "Thread is running..." << std::endl;
    }


    catch (boost::thread_interrupted&)
    {
       std::cout << "The thread is interrupted" << std::endl;

       throw boost::thread_interrupted();
    }

}

int main(int argc, char *argv[])
{
    boost::thread t(foo);

    std::cout << "Press Enter to quit..." << std::endl;
    std::cin.get();
    t.interrupt();
    //t.join();

    if (!t.try_join_for(boost::chrono::milliseconds(1)))
    {
        std::cout << "Thread is running." << std::endl;
    }
    else
    {
        std::cout << "Thread is not running." << std::endl;
    }

    //t.join();
    boost::this_thread::sleep_for(boost::chrono::milliseconds(1000));

    // The out put should be "Thread is running.", because thread is not joinalb, the test function itself is wrong.
    if (!t.try_join_for(boost::chrono::milliseconds(1)))
    {
        std::cout << "Thread is running." << std::endl;
    }
    else
    {
        std::cout << "Thread is not running." << std::endl;
    }
}
于 2015-09-18T06:42:59.473 に答える