多线程的问题:为什么改一个BOOL量会失败?在线等

Kaile 2005-10-24 08:05:41
一个线程对象正在跑,做一些科学计算工作,现在需要按一个按钮将这个对象的数据成员bExit由FALSE改为TRUE,以实现计算中断,结果发现没有任何效果。

请教,简捷的实现方法是什么?

谢谢。

...全文
207 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
bm1408 2005-10-25
  • 打赏
  • 举报
回复
你要重载消息处理的函数了,
我以前也遇到一个这样的问题,实在搞不定,我来
goodname008 2005-10-25
  • 打赏
  • 举报
回复
无论你在任何地方修改 bContinue 变量的值,都要做好线程同步,切记切记。
不然程序复杂了以后会很难排查错误。
Kaile 2005-10-25
  • 打赏
  • 举报
回复
感谢,发现是我的问题,我还有另外一个地方在SetExitFlag(TRUE)以后又将它变为FALSE,因为是多线程,改了以后没发现,以为是没修改成功。

上面的代码很好,学习。
goodname008 2005-10-25
  • 打赏
  • 举报
回复
而我个人比较推荐这种作法:

#include "stdafx.h"
#include "windows.h"
#include "process.h"
#include <iostream>
using namespace std;

HANDLE hEvent = NULL;

BOOL bContinue = TRUE;

unsigned int __stdcall ThreadProc(LPVOID lpParameter)
{
while (true)
{
if (WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0)
{
break;
}
Sleep(100);
}
cout << "Thread terminated." << endl;
return 0;
}

int main(int argc, char* argv[])
{
hEvent = CreateEvent(NULL, TRUE, FALSE, "TestEvent");
UINT nThreadID = 0;
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadProc, NULL, 0, &nThreadID);

int nInput = 0;
cin >> nInput;
if (nInput == 1)
{
SetEvent(hEvent);
}

WaitForSingleObject(hThread, INFINITE);

CloseHandle(hThread);

if (hEvent)
{
CloseHandle(hEvent);
hEvent = NULL;
}

return 0;
}
goodname008 2005-10-25
  • 打赏
  • 举报
回复
输入1可以使ThreadProc线程结束。
否则主线程将会被ThreadProc永远阻塞住。
goodname008 2005-10-25
  • 打赏
  • 举报
回复
#include "stdafx.h"
#include "windows.h"
#include "process.h"
#include <iostream>
using namespace std;

CRITICAL_SECTION cs;

BOOL bContinue = TRUE;

unsigned int __stdcall ThreadProc(LPVOID lpParameter)
{
while (true)
{
EnterCriticalSection(&cs);
if (!bContinue)
{
break;
}
LeaveCriticalSection(&cs);

Sleep(100);
}
cout << "Thread terminated." << endl;
return 0;
}

int main(int argc, char* argv[])
{
InitializeCriticalSection(&cs);

UINT nThreadID = 0;
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadProc, NULL, 0, &nThreadID);

int nInput = 0;
cin >> nInput;
if (nInput == 1)
{
EnterCriticalSection(&cs);
bContinue = FALSE;
LeaveCriticalSection(&cs);
}

WaitForSingleObject(hThread, INFINITE);

CloseHandle(hThread);
DeleteCriticalSection(&cs);

return 0;
}
peiming_ge 2005-10-25
  • 打赏
  • 举报
回复
在改变标志前先把线程对象挂起,试试
CWinThread* pCalc
....
main::SetExitFlag()
{
pCalc->SuspendThread()
pCalc->m_bExit = TRUE;
pCalc->ResumeThread();
}
皮皮鲁 2005-10-24
  • 打赏
  • 举报
回复
应该不大会的

可能是因为SetExitFlag在测试if ( isTimeOut() || m_bExit )之后运行

请确保在测试之前,已经调用了SetExitFlag
Kaile 2005-10-24
  • 打赏
  • 举报
回复
不行啊,大哥,我加了volatile,发现还是没改过来。

这样定义:
volatile BOOL m_bExit ;

这是调用对象的方法来修改这个标志
CalcInstance.SetExitFlag(TRUE);

void Calc::SetExitFlag(BOOL bExit)
{
m_bExit = bExit;
}

在计算内部加
if ( isTimeOut() || m_bExit )
  return ;

加断点,发现m_bExit仍然是FALSE

oyljerry 2005-10-24
  • 打赏
  • 举报
回复
用volatile 修饰,防止编译器作优化
然后线程中通过bCondition来跳出循环
ming6424 2005-10-24
  • 打赏
  • 举报
回复
同意楼上的!!!
皮皮鲁 2005-10-24
  • 打赏
  • 举报
回复
最简单的方法就是在你这个BOOL变量的定义前面加上volatile

如:
volatile BOOL bCondition;
gunney 2005-10-24
  • 打赏
  • 举报
回复
用临界区吧

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧