假设我有一个阻止方法,让我们在Block()中调用。
因为我不想让我的主线程阻塞我可能会创建一个工作线程,而是会调用Block。
然而,我有另一个条件。
我希望阻止调用在5秒内返回顶部,否则,我想让主线程知道对Block的调用失败并退出工作线程。
这种情况的最佳解决方案是什么?
我认为是这样的: 创建一个workher线程,在worker线程中创建一个5秒的计时器对象, 除了在调用Block之前和之后调用gettickcount并计算delta。另外我将定义一个布尔IsReturned指示Block函数是否已经返回。 在Block调用之后将其设置为true。
根据Timer函数中的布尔值,我决定如何继续:
如果布尔值为真,我什么都不做。
如果布尔值为false,我可以在主线程上排队APC OnFailure或者发出Sucess事件,并且强行退出工作线程(事情是我不确定我是否可以这样做)
此外,在阻止功能返回后,我检查增量是否为5秒 并排队APC OnSucess。 (问题是退出调用者线程也取消了定时器吗?因此基本上导致定时器无效)
p.s - 如果我可以确定我可以取消计时器功能中的工作线程,我认为我甚至不需要gettickcount的东西。
谢谢!
答案 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回复。所以你可以在那上建立你的超时。