繁体   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