2009-12-16 159 views
0

比方說,我有一個阻塞方法,讓我們在Block()中調用。線程同步

因爲我不希望我的主線程阻塞我可能會創建一個工作線程,而是會調用阻止。但是,我有另外一個條件。

我想調用阻塞在5秒內返回頂部,否則,我想讓主線程知道調用阻塞失敗並退出工作線程。

什麼是該方案的最佳解決方案?

我是這樣想的: 創建一個線程workher,在工作線程創建一個定時器對象,擁有5秒, 而且除了打電話的GetTickCount前後調用塊之後,計算的增量。

此外,我將定義一個布爾型IsReturned指示Block函數是否已經返回。 Block調用後將其設置爲true。

根據定時器功能是布爾我決定如何處理:

  1. 如果布爾是真實的我什麼也不做。

  2. 如果布爾是假的,我可以排隊的APC onFailure處或在主線程或許信號Sucess事件,forcfully退出工作線程(事情是我不知道如果我能做到這一點)

此外,在塊函數返回之後,我檢查增量是否是lett,然後是5秒 並排隊APC OnSucess。 (問題是退出來電線程取消定時器也基本上因爲定時器無用)

ps - 如果我可以肯定地知道我可以取消定時器功能內的工作線程我不認爲我甚至需要gettickcount的東西。

謝謝!

+1

你使用了什麼線程API?並行線程?提升線程? – mch 2009-12-16 00:54:11

+3

這是什麼阻塞方法?你不能利用windows IO完成端口和SleepEX()嗎? – 2009-12-16 00:54:33

+0

windows? Linux呢?蘋果系統? – 2009-12-16 03:41:37

回答

2

我建議使用這個boost :: threads庫。您可以定期檢查阻塞線程是否可連接(即仍在工作),然後在五秒鐘後中斷它。然後您需要編寫阻止函數來處理該中斷並完全退出。

#include <boost/thread/thread.hpp> 

void Block(void) 
{ 
    //Do work and periodically call boost::this_thread::sleep() 
    try 
    { 
     boost::this_thread::sleep(boost::posix_time::milliseconds(100)); 
    } 
    catch(boost::thread_interrupted const&) 
    { 
     return; 
    } 
} 

int main(int argc, char *argv[]) 
{ 
    boost::thread blockThread(Block); //If Block takes arguments, just add them as arguments to the constructor. 
    time_t startTime = time(NULL); 

    while(true) 
    { 
     if(blockThread.joinable() && (time(NULL) - startTime) > 5) 
     { 
      blockThread.interrupt(); 
     } 
     //Do whatever you want while waiting for the thread to finish. 
    } 
} 

編輯:檢查是否有更多的中斷點的Thread Management文檔和定義用於升壓線程類。編輯2:如果在等待阻塞線程完成時不需要在主線程中做任何工作,並且在Block()中沒有方便的地方處理中斷,則可以使用類似這樣的東西顯式地終止線程:

void Block(void) 
{ 
    //Do work 
} 

int main(args) 
{ 
    boost::thread blockThread(Block); 

    //timed_join() returns false if the thread is still running after the specified time. 
    if(!blockThread.timed_join(boost::posix_time::milliseconds(5000))) 
    { //detach() will kill the thread, any memory initialised in Block() will not be freed, any locals may or may not be freed either. 
     blockThread.detach(); 
    } 
} 
2

我認爲你有大致的想法,儘管你可能想要將WM_TIMER消息傳遞給主線程,而不是潛在的阻塞線程。否則,定時器消息可能會丟失,如果線程在定時器觸發之前阻塞!同樣,請檢查主線程中的工作時間,而不是工作人員,因爲如果Block()阻止,它將不會返回,Block()之後的GetTickCount()將永不會發生。

要在線程之間進行通信,最簡單的事情可能是使用一個原子變量。您也可以讓工作人員在成功時將消息傳遞迴主線程,並且如果主線程在5秒計時器觸發時看不到消息,則應該假定工作線程被阻塞。

一般來說,殺死阻塞的線程可能是危險的。 Java文檔強烈反對這樣做,如果有的話,使用C++的問題更加嚴重。考慮你自己的警告!

0

首先創建線程是一件昂貴的事情,因此每次對Block的調用可能不是一個好主意。

其次有很多方法可以解決這個問題,它也很大程度上取決於你的環境。例如,在Windows中,這樣做的一種可能方式是使工作線程具有消息隊列。然後定義一些您在工作線程中處理的消息。一個可能是WM_CALLBLOCK,另一個可能是WM_AREYOUREADY和WM_YESIAM,當你想調用Block()時,你可以把這個消息發佈到工作線程,它會調用這個函數。通過該消息,您還可以將Block()所需的任何參數傳遞給它。由於你的函數被阻塞 - 如果你發佈WM_AREYOUREADY消息,你將不會直接得到WM_YESIAM的回覆。所以你可以建立你的超時。