首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VC/MFC >

一个跟线程同步类似的有关问题,请各位帮帮看看出错原因

2012-01-16 
一个跟线程同步类似的问题,请各位帮帮看看出错原因有代码如下:C/C++ codebool g_IsReadThreadFinish tru

一个跟线程同步类似的问题,请各位帮帮看看出错原因
有代码如下:

C/C++ code
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.主现成开启线程后进入
C/C++ code
while (!g_IsReadThreadFinish)        {            Sleep(200);        }
等待;


这样看起来没有出问题,

可是调试的时候,怎么第一个线程都还没处理完,主线程又开启第二个线程了呢?
请指点!!!

[解决办法]
开始时没注意你的问题是创建了多于一个的线程,这估计是有内存越界或者使用了错误的指针而破坏了g_IsReadThreadFinish的值。
[解决办法]
因为Sleep的功能是暂停当前线程的CPU使用功能,切换到其他的线程去执行,你现在的代码很可能执行在主线程的while-Sleep循环中,每次执行到Sleep,然后线程切换到你创建的线程,而系统会发现所创建的线程执行的时间过长,系统又把CPU调度给你的主线程,这里就形成了一个来回的死循环。

我之前的回复可能没考虑好,但仍然建议你用WaitForSingleObject方法来等待线程结束
[解决办法]
在c++中编译时,如果发现在函数体内部没有改变某个变量的值,如g_IsReadThreadFinish,则函数体可能忽略该项值的检测,直接用初始值来代替,也就是说在OnBnClickedBtnSelect()函数体内,g_IsReadThreadFinish永远被编译成了false.试试使用volatile bool g_IsReadThreadFinish = true;替换原来的bool g_IsReadThreadFinish = true;


[解决办法]
在线程中访问控件可能会导致错误,因为VC中的控件都不是线程安全的,最好是通过SendNotifyMessage或者PostMessage,向控件发送消息来刷新显示,或者向窗口发送自定义消息,来处理。
[解决办法]
根据你的代码中得到的提示信息,你应该不能用WaitForSingleObject函数,原因在于这个函数是阻塞主线程的消息循环来等待,而你的ReadData线程会去操作CListCtrl来显示数据,这样会导致两个线程都阻塞住。

你的问题需要判断你的线程函数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); 

}
[解决办法]
可是调试的时候,怎么第一个线程都还没处理完,主线程又开启第二个线程了呢? 
——————
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执行完毕前的最后一句处。
[解决办法]

探讨
还有几点不清楚:
1.为什么用WaitForSingleObject会导致ReadData线程阻塞呢? 这个不理解
2.怎么判断和界面相关呢? 这是一个基于对话框的程序,在按钮的响应函数里通过创建线程读数据,然后显示在对话框上的CListCtrl.
感觉是和界面相关的,可是能确定
3.对你所列出的例子,因为以前没见过MsgWaitForMultipleObjects函数,
根据你的提示,我的理解如下,不知道对不对,请指正:
a.MsgWaitForMultipleObjects函数跟WaitForSingleObject不一样,后者是通过阻塞主线程消息循环来达到等待,所以当在ReadData线程操作主线程(对话框)上的
CListCtrl时,因为ReadData线程是通过向主线程发送某个消息来实现的.所以这时由于主线程处于阻塞状态,处理不了这个消息,从而导致了ReadData线程也处于一直
等待状态,
b.MsgWaitForMultipleObjects是不是阻塞主线程消息循环的,他根据返回的值,来判断执行何种操作.当等于WAIT_OBJECT_0,跳出该次循环,当不是,怎么处理消息


[解决办法]
如果楼主的数据线程里面没有去操作CListCtrl,是可以用WaitForSingleObject的,但是线程中一旦用了SendMessage之类的方法就不行了
[解决办法]
多线程同时操作一个变量会出问题的

热点排行