2013-10-07 23 views
1

我目前正在編寫一個使用boost線程的DLL。我遇到了使用boost :: thread :: interrupt()和捕獲thread_interrupted異常的問題。有了一些中斷字體,中斷被拋出並被捕獲到線程和其他線程中,中斷被引發到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時,中斷在主線程中被調用,但被工作線程捕獲。線程然後被銷燬。主線程然後繼續,程序退出。

我所看到的所有中斷點我都試過(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. 

這是什麼原因造成的?例如,如何在使用條件變量時捕獲worker函數中的中斷?我在某個地方犯了錯嗎?

我的代碼:

#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 ::螺紋和boost ::系統

感謝您的幫助

+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; 
    } 
} 
相關問題