我目前正在編寫一個使用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 ::系統
感謝您的幫助
你明白了嗎? – Dronz