线程同步

时间:2009-12-16 00:47:53

标签: c++ multithreading time synchronization

假设我有一个阻止方法,让我们在Block()中调用。

因为我不想让我的主线程阻塞我可能会创建一个工作线程,而是会调用Block。

然而,我有另一个条件。

我希望阻止调用在5秒内返回顶部,否则,我想让主线程知道对Block的调用失败并退出工作线程。

这种情况的最佳解决方案是什么?

我认为是这样的: 创建一个workher线程,在worker线程中创建一个5秒的计时器对象, 除了在调用Block之前和之后调用gettickcount并计算delta。

另外我将定义一个布尔IsReturned指示Block函数是否已经返回。 在Block调用之后将其设置为true。

根据Timer函数中的布尔值,我决定如何继续:

  1. 如果布尔值为真,我什么都不做。

  2. 如果布尔值为false,我可以在主线程上排队APC OnFailure或者发出Sucess事件,并且强行退出工作线程(事情是我不确定我是否可以这样做)

  3. 此外,在阻止功能返回后,我检查增量是否为5秒 并排队APC OnSucess。 (问题是退出调用者线程也取消了定时器吗?因此基本上导致定时器无效)

    p.s - 如果我可以确定我可以取消计时器功能中的工作线程,我认为我甚至不需要gettickcount的东西。

    谢谢!

3 个答案:

答案 0 :(得分:2)

我认为你有大致正确的想法,尽管你可能希望将WM_TIMER消息传递给主线程,而不是潜在的阻塞线程。否则,如果线程在计时器触发之前阻塞,则计时器消息可能会丢失!同样,检查主线程而不是工作线程中的已用时间,因为如果Block()阻止,它将不会返回,并且GetTickCount()之后Block()的调用永远不会发生。< / p>

要在线程之间进行通信,最简单的事情可能是使用原子变量。您也可以让工作人员在成功时将消息传递回主线程,如果主线程在5秒定时器触发时没有看到消息,则应该假定工作线程被阻塞。

通常,杀死被阻塞的线程可能很危险。 Java文档强烈反对这样做,如果有的话,C ++的问题会更严重。考虑自己警告!

答案 1 :(得分: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文档,了解更多中断点和boost thread类的定义。

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

答案 2 :(得分:0)

首先创建线程是一件昂贵的事情,因此每次调用Block都可能不是一个好主意。

其次,有很多方法可以解决这个问题,它也在很大程度上取决于您的环境。例如,在Windows中,执行此操作的可能方法是使工作线程具有消息队列。然后,您可以定义在工作线程中处理的几条消息。一个可能是WM_CALLBLOCK另一个可能是WM_AREYOUREADY和WM_YESIAM,当你想调用Block()时,你可以将该消息发布到工作线程,它会调用该函数。通过该消息,您还可以传递Block()所需的任何参数。由于您的功能正在阻止 - 如果您发布消息WM_AREYOUREADY,您将无法直接获得WM_YESIAM回复。所以你可以在那上建立你的超时。