有代码如下:
bool g_IsReadThreadFinish = true;DWORD WINAPI ReadData(LPVOID lpParameter)
{
g_IsReadThreadFinish = false;//线程开始 //处理过程
.......; g_IsReadThreadFinish = true;//线程结束 return 0;
}CXXXDlg::OnBnClickedBtnSelect()
{
vector<string>::iterator iterator = vectorTab.begin();
while (iterator != vectorTab.end())
{
.......; DWORD WINAPI ReadData(LPVOID lpParameter);
HANDLE handle=CreateThread(NULL,0,ReadData,NULL,0,NULL);
CloseHandle(handle);
g_IsReadThreadFinish = false; while (!g_IsReadThreadFinish)
{
Sleep(200);
}
iterator++;
}
}主线程的OnBnClickedBtnSelect()函数要连续几次通过创建相同线程进行处理,线程参数不一样
1.建线程后,将g_IsReadThreadFinish = false;
2.在线程处理函数中g_IsReadThreadFinish = false;
3.线程处理函数结束,g_IsReadThreadFinish = true;
4.主现成开启线程后进入while (!g_IsReadThreadFinish)
{
Sleep(200);
}等待;
这样看起来没有出问题,可是调试的时候,怎么第一个线程都还没处理完,主线程又开启第二个线程了呢?
请指点!!!
bool g_IsReadThreadFinish = true;DWORD WINAPI ReadData(LPVOID lpParameter)
{
g_IsReadThreadFinish = false;//线程开始 //处理过程
.......; g_IsReadThreadFinish = true;//线程结束 return 0;
}CXXXDlg::OnBnClickedBtnSelect()
{
vector<string>::iterator iterator = vectorTab.begin();
while (iterator != vectorTab.end())
{
.......; DWORD WINAPI ReadData(LPVOID lpParameter);
HANDLE handle=CreateThread(NULL,0,ReadData,NULL,0,NULL);
CloseHandle(handle);
g_IsReadThreadFinish = false; while (!g_IsReadThreadFinish)
{
Sleep(200);
}
iterator++;
}
}主线程的OnBnClickedBtnSelect()函数要连续几次通过创建相同线程进行处理,线程参数不一样
1.建线程后,将g_IsReadThreadFinish = false;
2.在线程处理函数中g_IsReadThreadFinish = false;
3.线程处理函数结束,g_IsReadThreadFinish = true;
4.主现成开启线程后进入while (!g_IsReadThreadFinish)
{
Sleep(200);
}等待;
这样看起来没有出问题,可是调试的时候,怎么第一个线程都还没处理完,主线程又开启第二个线程了呢?
请指点!!!
解决方案 »
- 高手帮忙,终止CWinThread派生线程的问题
- 怎么在设置ctabctrl中item的宽度,才能使ctabctrl在N多个页面的时候不出现页面的滚动条?就象Maxthon多页面浏览类似
- 折腾三天了:( 关于全局钩子dll中向 窗口发消息的问题。。。。急求帮助,感谢~~~
- 如何使用该函数
- 在给控件date time picker定义变量时COleDateTime m_date,运行程序时,弹出错误框:
- 有关画线格式的问题?
- 关于ODBC类中的 数据绑定
- 如何读ICON资源中的图标
- 结交准备学习VC的朋友!
- 求关于 GetModuleFileNameEx函数的解释
- Win CE上进度栏问题!
- UDP实现广播接收回复的例子
你的线程函数又没有进行互斥的判断。而且你这样简单的线程设计在开启多个线程函数后会有问题的。如果能确定线程函数的个数,建议你去看看WaitForMultiObject函数的用法,这才应该是标准的线程等待方法。
while (!g_IsReadThreadFinish)
{
Sleep(200);
}知道,创建的线程结束
while (!g_IsReadThreadFinish)
{
Sleep(200);
}
之前应该就有效果啊?并且在第一个创建的线程执行的前期过程
while (!g_IsReadThreadFinish)
{
Sleep(200);
}
语句是起了作用的
就是创建的第一个线程执行一段时间后,但还没结束,好象在现成中就始终运行不走了------按F10后,虽然还是在两个线程中切换,在创建的线程中找不到运行位置的提示了
所以主现成也始终处于睡眠状态了我在创建的线程入口函数结束前有语句
g_IsReadThreadFinish = true;//线程结束可是该入口函数根本就执行不到这一句来,在中间某个位置就不走了
//DWORD WINAPI ReadData(LPVOID lpParameter);
if(g_IsReadThreadFinish){
g_IsReadThreadFinish = false;
HANDLE handle=CreateThread(NULL,0,ReadData,NULL,0,NULL);
}
DWORD WINAPI ReadData(LPVOID lpParameter)
{
//g_IsReadThreadFinish = false;//线程开始 //处理过程
.......; g_IsReadThreadFinish = true;//线程结束
return 0;
}
但是,当我让创建线程只执行一次的时候 同时把Sleep(200)注释掉,这样现成入口函数可以完全执行
能这样理解吗?系统发现创建的线程执行的时间过长,就根本不会给创建的线程一段时间--时间片,让创建的线程执行下去,而是马上有把CPU调度分配给主线程?
HANDLE g_hMutex;DWORD WINAPI ReadData(LPVOID lpParameter)
{
WaitForSingleObject(g_hMutex,INFINITE);//线程开始 .......;//读取数据库,获得相关数据 .......;//将得到的数据显示在CListCtrl上 ReleaseMutex(g_hMutex);//线程结束 return 0;
}CXXXDlg::OnBnClickedBtnSelect()
{
...........
g_hMutex = CreateMutex(NULL,false,NULL); vector<string>::iterator iterator = vectorTab.begin();
while (iterator != vectorTab.end())
{
WaitForSingleObject(g_hMutex,INFINITE);
.......; DWORD WINAPI ReadData(LPVOID lpParameter);
HANDLE handle=CreateThread(NULL,0,ReadData,NULL,0,NULL);
CloseHandle(handle); ReleaseMutex(g_hMutex);
Sleep(10); //确保创建的现成获得g_hMutex; iterator++;
}
}在ReadData函数中,
当把".......;//读取数据库,获得相关数据"部分运行完后既而再运行".......;//将得到的数据显示在CListCtrl上"部分时,就不知道运行到那里去了所以主线程也始终获得不了g_hMutex当只创建一个线程的时候,所以也不用加上利用Mutex实现同步,
ReadData就能很好的完成.
如果你的回答是不,那么可以才可以用WaitForSingleObject来等待,我看你对WaitForSingleObject的用法好像也有问题。你应该用MsgWaitForMultipleObjects,这个函数才是既等待内核对象,又处理消息的。下面的while循环才是用来实现你的真正的等待,代码段仅供参考while(TRUE)
{
DWORD result ;
MSG msg ;
result = MsgWaitForMultipleObjects(1, &readThreadHandle,
FALSE, INFINITE, QS_ALLINPUT);
if (result == (WAIT_OBJECT_0))
{
break;
}
else
{
PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
DispatchMessage(&msg);
}
}
m_hThread=CreateThread();
WaitForSingleObject(m_hThread,INITFINE);
就可以了吧
请注意我前面的分析,楼主的线程函数也需要操作控件,不能简单的用WaitForSingleObject,会阻塞两个线程的,因为操作控件很可能会使用SendMessage这样的调用
——————
HANDLE handle=CreateThread(NULL,0,ReadData,NULL,0,NULL);
CloseHandle(handle);
g_IsReadThreadFinish = false; while (!g_IsReadThreadFinish)
{
Sleep(200);
}
——————
注意:CloseHandle(handle)并不是结束线程,而是释放线程句柄handle的资源。另外,进程的主线程有比子线程更高的优先级。
所以,上面代码中,线程创建后,还没等线程结束,而仅仅是当线程句柄释放后就急急地把g_IsReadThreadFinish设为false了。从你的描述来看,g_IsReadThreadFinish = false;这一句应当放到线程处理函数ReadData执行完毕前的最后一句处。
为什么用WaitForSingleObject会导致ReadData线程阻塞呢?
对这个不理解,麻烦解释下
还有几点不清楚:
1.为什么用WaitForSingleObject会导致ReadData线程阻塞呢? 这个不理解
2.怎么判断和界面相关呢? 这是一个基于对话框的程序,在按钮的响应函数里通过创建线程读数据,然后显示在对话框上的CListCtrl.
感觉是和界面相关的,可是能确定
3.对你所列出的例子,因为以前没见过MsgWaitForMultipleObjects函数,
根据你的提示,我的理解如下,不知道对不对,请指正:
a.MsgWaitForMultipleObjects函数跟WaitForSingleObject不一样,后者是通过阻塞主线程消息循环来达到等待,所以当在ReadData线程操作主线程(对话框)上的
CListCtrl时,因为ReadData线程是通过向主线程发送某个消息来实现的.所以这时由于主线程处于阻塞状态,处理不了这个消息,从而导致了ReadData线程也处于一直
等待状态,
b.MsgWaitForMultipleObjects是不是阻塞主线程消息循环的,他根据返回的值,来判断执行何种操作.当等于WAIT_OBJECT_0,跳出该次循环,当不是,怎么处理消息
麻烦解释下,再次感谢了!
再看时,又有疑惑了:
if (result == (WAIT_OBJECT_0)),你用的是break,即结束循环,
如果用的是continue,我能理解.在主线程的执行时间周期里,不停的判断MsgWaitForMultipleObjects的返回值,当result == (WAIT_OBJECT_0)时,跳出本次循环
,如果不是,责表明有其他消息(ReadData线程操作CListCtrl传来的)传来需要处理,如果主线程的时间周期还没结束,就处理该消息.当主线程执行时间周期结束后,又
把CPU控制全转交给ReadData线程,如果对CListCtrl的操作已经完成,那么ReadData线程线程就继续执行操作CListCtrl之后的代码
应该明确线程争用的资源是什么,在子线程中控制访问冲突。
前面有人说了, 编译器优化的问题
你的a这点的理解基本正确的,这也回答了你的第一个问题。
2.
判断的方式很简单,你就看ReadData中你是如何操作CListCtrl的,可以需要进一步阅读MFC的代码。
3.MsgWaitForMultipleObjects的用法就是我上面给的代码
我的做法是在新建线程的代码中设定一个变量,然后根据这个变量直接Return来退出线程.
谢谢,你给的例子里
if (result == (WAIT_OBJECT_0))
{
break;
}
break能换成continue吗?
这样理解:
在主线程的执行时间周期里,不停的判断MsgWaitForMultipleObjects的返回值,当result == (WAIT_OBJECT_0)时,跳出本次循环
继续下次循环,如果不是,责表明有其他消息(ReadData线程操作CListCtrl传来的)传来需要处理,如果主线程的时间周期还没结束,就处理该消息.当主线程执行时间周期结束后,
就把CPU控制全转交给ReadData线程,如果对CListCtrl的操作已经完成,那么ReadData线程线程就继续执行操作CListCtrl之后的代码
LZ是想用Sleep来代替烦人的互斥对象,这个最好放在线程内部随便设一个全局变量 b=false;
[code=C/
DWORD WINAPI ReadData(LPVOID lpParameter)
{
while(b)
Sleep(1); b=true; ...
...
...
b=false;
return 0;
} C++][/code]
在主線程創建互斥量,也在主線程釋放,保證只有一個線程在運行。次線程中不要去釋放互斥量。
楼主你的线程函数里面前面不要WaitForSingleObject了,你前面已经在主线程中
使用WaitForSingleObject了,所以线程函数中等待就会死锁,挂在那里,所以系统就挂了。
只要把线程函数前的WaitForSingleObject去掉就可以了。
还有你如果调试不要只在主线程中打断点然后按F10,在子线程中也打个断点,然后按F10,
这样你就可以看到程序在两个线程中切换执行了。
请注意,ReadData线程里没有使用你说的while(b)的循环,而是处理完了就执行b=false;
之所以出现最后2个线程等待的原因,应该还是如同22楼分析的那样,主线程已经Sleep了,由于在ReadData线程有和界面相关,所以导致了两个线程都阻塞住欢迎探讨
用WaitForSingleObject导致你程序死锁是因为你在子线程中也用了WaitForSingleObject,只要把子线程中的WaitForSingleObject去掉就行了。。
还有这里不需要判断返回值,因为你时间指定的是INFINITE
觉得不是这个原因:ReadData线程只是在处理跟界面相关代码的时候发生阻塞的,应该不能用WaitForSingleObject,而是用MsgWaitForMultipleObjects,如同22楼说的个道理
晕死。你先搞清楚WaitForSingleObject的意思再说吧。如果一个线程调用了WaitForSingleObject锁住g_hMutex另外一个线程再调用WaitForSingleObject还能继续才怪呢!!
22楼那个有什么用啊。你又不是多个事件对象。有毛用。。
没注意楼主代码中主线程也有ReleaseMutex,呵呵。。
我在ReadData线程里,没有使用SendMessage,也没PostMessage,
而是在GetDlgItem来获取CListCtrl的,进而向CListCtrl中插入数据,请问这算界面相关吗?
而是在ReadData线程通过GetDlgItem来获取CListCtrl的,进而向CListCtrl中插入数据,请问这算界面相关吗?
{
.......; DWORD WINAPI ReadData(LPVOID lpParameter);
HANDLE handle=CreateThread(NULL,0,ReadData,NULL,0,NULL);
CloseHandle(handle);
g_IsReadThreadFinish = false; while (!g_IsReadThreadFinish)
{
Sleep(200);
}
iterator++;
}
你这段代码有问题 当然会不停创建啦。
你简化一下看看?
while(p->next!= null)
{
createthread;
nn = false;
if(!nn) sleep(200)
p = p->next;
}
你这段代码的意思是 如果p不为空 创建线程 等待200毫秒 p指向下一个对象
如果下一个对象有 那么接着创建线程。。在200毫秒。。如此重复。
这么多高手 难道都没有看出来吗?
你们的解决方法我不懂。
但是这段代码它就是会不停创建。
g_IsReadThreadFinish = false;
::LeaveCriticalSection(&m_CriticalSectionLock);
首先你是不是想启动一个后台线程帮你处理vectorTab里面的数据。
如果是的话什么需要处理一个vectorTab里面的元素就创建一个线程。
其实一开是的while循环就可以放在后台线程中的。
然后你说第一个线程还未执行完就产生第二个线程,这个问题我使过了好像是不会出现的。代码如下:
bool g_IsReadThreadFinish = true;DWORD WINAPI ReadData(LPVOID lpParameter)
{
int r=(int)lpParameter;
g_IsReadThreadFinish = false;//线程开始 cout<<"线程"<<r<<"执行当中!"<<endl; g_IsReadThreadFinish = true;//线程结束
cout<<"线程"<<r<<"结束!"<<endl;
return 0;
}
void main()
{
int i=0;
while(1)
{
HANDLE threadHandle=CreateThread(NULL,0,ReadData,(LPVOID)i,0,NULL);
CloseHandle(threadHandle);
g_IsReadThreadFinish=false;
while (!g_IsReadThreadFinish)
{
Sleep(200);
}
i++;
}
}
还有上面所说的使用互斥量,其实是你使用的不正确,你的互斥不应该是和主线程互斥,而是后台线程中的互斥。
直接将你主线程中的waitforsingleobject和releasemutex函数去掉即可。