C++ 主应用程序处于while循环时boost线程未运行
我对使用boost线程相当陌生。我几乎有东西在运行,但遇到了一个绊脚石:任何帮助都将不胜感激 我有一个VC++(VS2010 Windows窗体)应用程序。在不久的将来,这需要移植到C++和Linux上,所以我用Boost库来处理线程,以“轻松”端口。 我在执行某些I/o的类中有一个辅助函数:C++ 主应用程序处于while循环时boost线程未运行,c++,multithreading,boost,sleep,C++,Multithreading,Boost,Sleep,我对使用boost线程相当陌生。我几乎有东西在运行,但遇到了一个绊脚石:任何帮助都将不胜感激 我有一个VC++(VS2010 Windows窗体)应用程序。在不久的将来,这需要移植到C++和Linux上,所以我用Boost库来处理线程,以“轻松”端口。 我在执行某些I/o的类中有一个辅助函数: void myClass::doIO{ while (!boolKillthread){ //do some work //sleep thread boost:
void myClass::doIO{
while (!boolKillthread){
//do some work
//sleep thread
boost::this_thread::sleep_for(boost::chrono::milliseconds(333));
}
}
它在一个boost线程中启动:
boost::thread m_MyThread;
m_MyThread = boost::thread(boost::bind(&myClass::doIO));
这工作得很好,i/o端口正在被轮询,并且正在完美地回调到父类中。但是:
我还有一个函数需要等待doIO线程来执行一些工作,因此我有一个函数,代码如下:
while (myClass.IsWorkDone() == true){
//hang a around a while
//lines commented out below have been tried, but don't resolve the problem
//boost::this_thread::yield();
//boost::this_thread::sleep(boost::posix_time::milliseconds(50));
//boost::this_thread::sleep_for(boost::chrono::milliseconds(50));
}
问题是,只要我的代码进入while循环,boost线程doIO就会停止——几乎就像它没有在自己的线程中运行一样!我已经试着按照上面注释掉的行插入sleeps和yields,但没有效果
有什么想法吗
谢谢大家的回答:是的,(伪代码)“IsWorkDone”只是返回一个变量,所以我理解(现在已经尝试)使用boost::mutex::scoped_锁来更新该变量,所以我们有
bool myWorkIsDone = false;
bool myClass::IsWorkDone{ return myWorkIsDone; }
void myClass::doIO{
while (!boolKillthread){
//do some work
if (SomeCondition){
boost::mutex::scoped_lock lock(myMutex);
myWorkIsDone = true;
}
//sleep thread
boost::this_thread::sleep_for(boost::chrono::milliseconds(333));
}
}
这很好,但关键是(除非我遗漏了一些明显的东西,这是完全可能的),当我的主代码在循环中时,线程似乎没有运行
while(myClass.IsWorkDone()==true){
因为IDE通常会在doIO中的断点上停止,但在上面的while循环中执行时不会停止
真的没有更多的代码(相关的)要添加了-它应该很简单,但不起作用!iWorkdone看起来像什么?它看起来像这样吗:
bool IsWorkDone() const { return workdone_; }
因为如果是这样的话,那就是你的问题。你需要使用互斥来包装对workdone\uu
的访问。这是共享状态,共享状态需要一个互斥。编译器可能正在读取循环顶部的变量,而不再费心再次读取它。毕竟,据它所知,没有任何理由改变它,所以再看一遍没有意义了
即使它再次读取它,CPU也有一个很好的缓存线来保存它,它可能永远不会被刷新,所以你只是在读取它
哦,当你设置它时,也需要一个互斥
把它变成一个
::std::atomic
实际上是一个更好的主意,但我猜你还没有这个想法。IO操作中有互斥吗?我不得不在我的答案中猜测这个问题,因为这里没有足够的代码知道。:boost::thread
最肯定的是总是创建一个新的执行线程。所以你的代码一定在做有什么问题。你能强行闯入另一个线程吗?顺便说一句,boolKillthread
也会有同样的问题是myWorkIsDone
,但这可能不是你的问题。你的另一个线程显然在阻塞某些东西。显而易见的选择是它在IO上阻塞,但可能在等待互斥锁或其他什么。使用“do”有些作品的注释都是这样的:这个线程应该可以正常工作。我敢打赌,如果你删除原始代码中的所有作品,它会正常工作。@Omnifarious:谢谢你的帮助。我用一个伪函数重新实现了我的main doIO,以测试其他东西正在阻塞的理论——事实似乎确实如此函数线程似乎运行正常。(我现在的挑战是找出什么是-但那是另一个故事!)好的,了解互斥体,谢谢,我会尝试。但是-如果我在doIO函数中放置断点,它会在正常(UI空闲)执行时被击中,但不是在代码处于while(myClass.IsWorkDone()==true){…}时被击中循环。不需要互斥锁,volatile将起作用。vloatile
关键字指示编译器可以从外部更改变量,因此不能进行积极缓存或优化。不,volatile对于多线程是错误的。它在Visual Studio中会做正确的事情,但在GCC中不会。由于他正在移植,int生成VS依赖项是错误的做法。std::atomic是一个更好的主意,但这当然要求VS更新到2012。@Lazin:这是一个非常错误的答案。这是一个危险的错误,因为它表面上看起来是正确的。它完全无法解决缓存线问题。是的,另一个注释是正确的,::std::atomic
w我会的,但我假设没有C++11,因为OP使用的是::boost::thread
@Zippy:您没有显示足够的代码,我无法告诉您哪里出了问题。
bool IsWorkDone() const { return workdone_; }