2013-10-07 4 views
1

현재 부스트 스레드를 사용하는 DLL을 작성 중입니다. boost :: thread :: interrupt()를 사용하고 thread_interrupted 예외를 catch하는 데 문제가 있습니다. 일부 인터럽트 폰트의 경우 인터럽트가 발생하여 스레드와 다른 스레드에서 잡히면 인터럽트가 발생하고 thread.interrupt()가 호출됩니다. 왜 이런 일이 생길까요? 내 요점을 설명하기위한 기본적인 예제를 작성했습니다.이 게시물의 맨 아래에 있습니다.Boost :: thread :: interrupt()는 다른 인터럽트 지점에 대해 다르게 동작합니다. 왜?

프로그램은 서로 다른 인터럽트 지점이있는 작업자 기능 중 하나를 사용하는 스레드를 시작합니다. 사용자가 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 키를 누르면 인터럽트는 주 스레드에서 호출되지만 작업자 스레드에서 catch됩니다. 그런 다음 스레드가 삭제됩니다. 그런 다음 주 스레드가 계속 진행되고 프로그램이 종료됩니다.

내가 인터럽트 지점 (나는 interrupt_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을 사용하고 있습니다. 나는 :: 향상을 위해 스레드를 런타임 링크 정전기, 멀티 스레딩 라이브러리를 사용하고 향상하고 :: 시스템 당신의 도움이

+0

알아 냈습니까? – Dronz

답변

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; 
    } 
}