簡體   English   中英

線程同步

[英]thread synchronization

假設我有一個阻塞方法,讓我們在Block()中調用。

因為我不希望我的主線程阻塞,所以我可能會創建一個工作線程,而是調用Block。

但是,我還有另一個條件。

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

那種情況下最好的解決方案是什么?

我想過這樣的事情:創建一個工作線程,在工作線程中創建一個5秒的計時器對象,並在調用Block之前和之后調用gettickcount並計算增量。

另外,我將定義一個布爾值IsReturned,指示Block函數是否已經返回。 在Block調用之后將其設置為true。

根據計時器函數中的布爾值,我決定如何繼續:

  1. 如果布爾值是真的,我什么也不做。

  2. 如果布爾值為假,我可以在主線程上排隊APC OnFailure或發出信號Sucess事件,然后強制退出工作線程(問題是我不確定是否可以這樣做)

另外,在返回塊函數之后,我將檢查增量是否為5秒,然后將APC OnSucess排隊。 (問題是退出調用者線程也取消了計時器嗎?基本上是在計時器無用之后造成的)

ps-如果我可以確定我可以取消計時器函數中的工作線程,我不認為我什至不需要gettickcount東西。

謝謝!

我認為您的想法大致正確,盡管您可能希望將WM_TIMER消息傳遞到主線程,而不是可能阻塞的線程。 否則,如果線程在計時器觸發之前阻塞,則計時器消息可能會丟失! 同樣,檢查主線程而不是工作線程中的經過時間,因為如果Block()阻塞,它將不會返回,並且Block()之后對GetTickCount()的調用將永遠不會發生。

在線程之間進行通信,最簡單的方法可能是使用原子變量。 您還可以讓工作線程在成功時將消息傳遞回主線程,並且如果在5秒計時器觸發時主線程沒有看到消息,則應假定工作線程被阻塞。

通常,殺死被阻塞的線程可能很危險。 Java文檔強烈警告不要這樣做,如果有的話,C ++的問題會更嚴重。 考慮一下自己被警告!

我建議為此使用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.
    }
}

編輯:檢查線程管理文檔以獲取更多中斷點和boost線程類的定義。

Edit2:如果在等待阻塞線程完成時不需要在主線程中做任何工作,並且在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();
    }
}

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

其次,有很多方法可以解決此問題,這也很大程度上取決於您的環境。 例如,在Windows中,執行此操作的一種可能方法是使工作線程具有消息隊列。 然后,您定義一些在工作線程中處理的消息。 一個可能是WM_CALLBLOCK,另一個可能是WM_AREYOUREADY和WM_YESIAM,當您要調用Block()時,您可以將該消息發布到工作線程中,然后它將調用該函數。 通過該消息,您還可以傳遞Block()所需的任何參數。 由於您的功能正在阻止-如果您隨后發布消息WM_AREYOUREADY,則不會直接收到WM_YESIAM答復。 因此,您可以在此基礎上建立超時。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM