2009-12-16 168 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的回复。所以你可以建立你的超时。