一个MsgWaitForMultipleObjects函数的问题!解决五体投地的感谢!

longgang521125 2012-02-22 03:46:34
DWORD dRet=0;
MSG msg;
//int nExitThreadCount=0,totalThread=Threadcount;

while(1)
{
dRet=::MsgWaitForMultipleObjects(Threadcount,hThreadp,FALSE,INFINITE,QS_ALLINPUT);
if(dRet==WAIT_OBJECT_0+Threadcount)
{
while (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
if (dRet>=WAIT_OBJECT_0 && dRet<WAIT_OBJECT_0+Threadcount)
{
nExitThreadCount++;
if(Threadcount!=0){
int Index=dRet-WAIT_OBJECT_0;
hThreadp[Index]=hThreadp[Threadcount-1];
hThreadp[Threadcount-1]=NULL;
Threadcount--;}
else
{break;}

}

}
...全文
1084 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
钱塘民工 2012-10-08
  • 打赏
  • 举报
回复
http://blog.csdn.net/silvervi/article/details/5874212
钱塘民工 2012-10-08
  • 打赏
  • 举报
回复
while (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
直接替换成:PeekMessage(&msg,NULL,0,0,PM_REMOVE)
longgang521125 2012-02-22
  • 打赏
  • 举报
回复
线程卡住了?那我看看吧,但是..我也不知道怎么说了,我同事用了一种方法又能实现,就是在吧那个什么MSG什么的函数结构改了下就可以了!谢谢你啊!
hotpos 2012-02-22
  • 打赏
  • 举报
回复
你线程卡住了吧, 估计
longgang521125 2012-02-22
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 hotpos 的回复:]
C/C++ code

DWORD WINAPI ThreadFun(LPVOID threadParam)
{
int n = (int)threadParam;
for (int i=0; i<n; i++)
{
Sleep(1000);
}

printf("thread %d quit.\n", n);
……
[/Quote]
你这个能运行额,我那个为什么呢?
hotpos 2012-02-22
  • 打赏
  • 举报
回复

DWORD WINAPI ThreadFun(LPVOID threadParam)
{
int n = (int)threadParam;
for (int i=0; i<n; i++)
{
Sleep(1000);
}

printf("thread %d quit.\n", n);
return 0;
}

void WaitForThreadQuit(HANDLE hTheads[], int threadCount)
{
MSG msg;

while(threadCount > 0)
{
DWORD dRet = MsgWaitForMultipleObjects(threadCount,hTheads,FALSE,INFINITE,QS_ALLINPUT);

if (dRet == (WAIT_OBJECT_0 + threadCount))
{
while (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else if ((dRet>=WAIT_OBJECT_0) && (dRet<WAIT_OBJECT_0 + threadCount))
{
int quitIndex = dRet - WAIT_OBJECT_0;

printf("hTheads[%d] quit.\n", quitIndex);

HANDLE hThread = hTheads[quitIndex];
hTheads[quitIndex] = hTheads[--threadCount];
hTheads[threadCount] = hThread;
}
}
}

int _tmain(int argc, _TCHAR* argv[])
{
const int threadCount = 6;
HANDLE hThreads[threadCount] = {0};

for (int i=0; i<threadCount; i++)
{
hThreads[i] = CreateThread(NULL, 0, ThreadFun, (LPVOID)(i+1), 0, NULL);
}

WaitForThreadQuit(hThreads, threadCount);
printf("all thread quit.\n");

return 0;
}


你运行下看看
longgang521125 2012-02-22
  • 打赏
  • 举报
回复
void CCallWebService::OnBnClickedButton1()
{
BeginWaitCursor(); //鼠标变成等待
CString strtext;

((CButton*)GetDlgItem(IDC_BUTTON1))->GetWindowText(strtext);
if (_T("CallWebService")==strtext)
{
CString strXmlElem;
isexit=false;
//m_buttonCtrl.LoadBitmaps(IDB_BITMAP2);
CString strunm;
m_combCrtl.GetWindowText(strunm);
Threadcount=atoi(strunm);
if (Threadcount<=0)//线程数量 少于0 就不处理
{
MessageBox(_T("Please first create XML account file or Check the XML file!"),_T("CallWebService"),MB_OK|MB_ICONEXCLAMATION);
return;
}
m_buttonCtrl.EnableWindow(FALSE);
m_combCrtl.EnableWindow(FALSE);//禁用 下拉列表框
if(m_listmsg.GetItemCount()>0)//列表不为空就 删除所有的
m_listmsg.DeleteAllItems();
if(NULL!=hThreadp)
{
delete []hThreadp;
hThreadp=NULL;
}
hThreadp = new HANDLE[Threadcount+1];
for (int i=0;i<Threadcount;i++)//先读取xml中的配置文件
{
UserNameMsg *namemsg=new UserNameMsg;//要在这里 new一个区域,否则传入到线程中会出问题,删除的时候由线程完成
namemsg->s_dlg=this;
strXmlElem.Format(_T("%d"),(i+1));
strXmlElem=_T("AccountInfo")+strXmlElem;//读取对应的xml 项下的信息
//OutputDebugString(strXmlElem);
if (m_XmlFile.FindElem(strXmlElem))
{
m_XmlFile.IntoElem();//进入下一个目录
if (m_XmlFile.FindElem(_T("UserName")))
namemsg->str_name=m_XmlFile.GetData();
else
namemsg->str_name=_T("nanjun@test.com");//默认就会调用这个账号

if (m_XmlFile.FindElem(_T("Password")))
namemsg->str_pwd=m_XmlFile.GetData();
else
namemsg->str_pwd=_T("e10adc3949ba59abbe56e057f20f883e");
m_XmlFile.OutOfElem();//退回去
m_XmlFile.ResetMainPos();//要 置回去,否则多次访问的时候会出现问题
}
else
{
namemsg->str_name=_T("nanjun@test.com");//默认账号
namemsg->str_pwd=_T("e10adc3949ba59abbe56e057f20f883e");
}
namemsg->pidnumb=mpidnu;
namemsg->strLang=mlanguage;
namemsg->strCountry=mcountry;
CWinThread* pWinT=AfxBeginThread(&CallWebTheread,LPVOID(namemsg));
hThreadp[i] = pWinT->m_hThread;
}
((CButton*)GetDlgItem(IDC_BUTTON1))->SetWindowText(_T("StopCall"));
m_buttonCtrl.EnableWindow(TRUE); //开启这个按钮
//isrunTd=true;
}
else
{
isexit=true;
m_buttonCtrl.EnableWindow(FALSE);
m_ButtonSave.EnableWindow(FALSE);
m_WaitFlag=true; //鼠标变成等待

//WaitForMultipleObjects(Threadcount,hThreadp,TRUE,INFINITE);// 这个会使主界面卡死

//等待线程结束,因为要在主界面上面添加记录,所以要刷新界面WaitForMultipleObjects会阻塞,
// 改用MsgWaitForMultipleObjects实现
DWORD dRet=0;
MSG msg;
//int nExitThreadCount=0,totalThread=Threadcount;

while(1)
{
dRet=::MsgWaitForMultipleObjects(Threadcount,hThreadp,FALSE,INFINITE,QS_ALLINPUT);
if(dRet==WAIT_OBJECT_0+Threadcount)
{
while (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
if (dRet>=WAIT_OBJECT_0 && dRet<WAIT_OBJECT_0+Threadcount)
{
nExitThreadCount++;
if(Threadcount!=0){
int Index=dRet-WAIT_OBJECT_0;
hThreadp[Index]=hThreadp[Threadcount-1];
hThreadp[Threadcount-1]=NULL;
Threadcount--;}
else
{break;}

}

}


//bool isforce=false;
//for(int j=0;j< Threadcount ;j++)
//{
//while (1)
//{
//dRet=::MsgWaitForMultipleObjects(1,hThreadp +j,FALSE,INFINITE,QS_ALLINPUT);//每次等待一个结束
//if (dRet == WAIT_OBJECT_0 + 1)
//{//在这里有可能卡死,具体原因还不清楚
// while (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
// {
// TranslateMessage(&msg);
// DispatchMessage(&msg);
// }
// if(nExitThreadCount==Threadcount)//获得的退出数量和线程数量一致的时候 强制退出
// {
// isforce=true;
// break;
// }
//}
//else
//{
// break;
//}
//if ((dRet >= WAIT_OBJECT_0) && (dRet < WAIT_OBJECT_0 + Threadcount))
//{
// nExitThreadCount++;
// if (nExitThreadCount < totalThread)//一个线程退出了
// {
// TRACE("一个线程退出了\n");
// int nIndex=dRet-WAIT_OBJECT_0;//退出的线程 数组中的
// for (int nj=nIndex;nj<Threadcount;nj++)
// {
// hThreadp[nj]=hThreadp[nj+1];
// }
// hThreadp[Threadcount-1]=NULL;
// Threadcount--;
// }
// else
// {
// break;
// }
//}
//else
//{
// DWORD dErrCode=GetLastError();
// break;
//}
//}
/*if (isforce)
{
nExitThreadCount=0;
break;
}*/
//OutputDebugString(_T("MsgWaitForMultipleObjects111111111111"));
//}
if (hThreadp!=NULL)
{
delete []hThreadp;
hThreadp=NULL;
}
((CButton*)GetDlgItem(IDC_BUTTON1))->SetWindowText(_T("CallWebService"));
m_combCrtl.EnableWindow(TRUE);
m_buttonCtrl.EnableWindow(TRUE); //开启这个按钮
m_ButtonSave.EnableWindow(TRUE);
m_WaitFlag=false; //结束鼠标等待状态
}
EndWaitCursor(); //结束鼠标等待状态
}
longgang521125 2012-02-22
  • 打赏
  • 举报
回复
UINT CCallWebService::CallWebTheread(LPVOID pParam)
{
UserNameMsg *msgdlg=(UserNameMsg *)pParam;
CCallWebService *dlg=msgdlg->s_dlg;

CTime mtim;
CString strtime,speedT;
CString slang = msgdlg->strLang;
int pid = msgdlg->pidnumb;
CString sCountry = msgdlg->strCountry;
DWORD oldtime,sptime;

if (SUCCEEDED(CoInitialize(NULL)))
{
CSecurity getToken;
Security::GenericMessage logmsg;
ParentChildConsoleReturn parentMsg;
HRESULT hr;

BSTR name=(msgdlg->str_name).AllocSysString();
BSTR paswd=(msgdlg->str_pwd).AllocSysString();

BSTR stoken;
bool exitmak=false;
while(TRUE)//循环 调用webservice
{
if (dlg->isexit)
{
dlg->InsertInfo(_T(""),_T(""),_T(""),false,_T(""));
break;
}
mtim = CTime::GetCurrentTime();
strtime=mtim.Format("%Y-%m-%d %H:%M:%S");//访问开始时间
oldtime=GetTickCount();
hr=getToken.eMailLogin(name,paswd,&parentMsg);//得到 token
sptime=(GetTickCount()-oldtime);// 计算时间差
speedT.Format(_T("%d ms"),sptime);
if (SUCCEEDED(hr))
{
//OutputDebugString(_T("eMailLogin success!"));
stoken=parentMsg.sToken;
dlg->InsertInfo(strtime,_T("eMailLogin"),speedT,false,dlg->path1);
if (!(dlg->TokenTraverse(stoken,pid,slang,sCountry,paswd)))//返回值为 false 也就是 退出的标志
{
exitmak=true;
}
if (!(dlg->TraverseNoToken(pid,slang,sCountry)))
{
exitmak=true;
}
}
else//登陆失败 现在继续访问不需要token的,或者是改成登陆失败继续登陆?
{
dlg->InsertInfo(strtime,_T("eMailLogin"),speedT,true,dlg->path1);
if (!(dlg->TraverseNoToken(pid,slang,sCountry)))//返回值为 false 也就是 退出的标志
{
exitmak=true;
}
}
mtim = CTime::GetCurrentTime();
strtime=mtim.Format("%Y-%m-%d %H:%M:%S");//访问开始时间
oldtime=GetTickCount();
hr=getToken.logout(&logmsg);
sptime=(GetTickCount()-oldtime);// 计算时间差
speedT.Format(_T("%d ms"),sptime);
if (SUCCEEDED(hr))
dlg->InsertInfo(strtime,_T("logout"),speedT,false,dlg->path1);
else
dlg->InsertInfo(strtime,_T("logout"),speedT,true,dlg->path1);
//OutputDebugString(_T("logout 00000000000000"));
if (exitmak)
{
break;
}
Sleep(500);
}
SysFreeString(name);
SysFreeString(paswd);
//CoUninitialize();//会导致程序崩溃,具体原因不清楚,感觉手动清除com组件有问题?
}
else
{
AfxMessageBox(_T("CoInitialize fail!"));
}
delete msgdlg;
return 0;
}
longgang521125 2012-02-22
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 hotpos 的回复:]
不会啊。 代码我看看
[/Quote]
所有的?有蛮多啊!
hotpos 2012-02-22
  • 打赏
  • 举报
回复
不会啊。 代码我看看
longgang521125 2012-02-22
  • 打赏
  • 举报
回复

hotpos
大神,你说说我这个为什么线程那段if不执行?这是为什么?你能说说嘛?
longgang521125 2012-02-22
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 hotpos 的回复:]
QS_ALLINPUT会使有任何的消息到达消息队列都会结束 MsgWaitForMultipleObjects 的等待,包括键盘、鼠标、以及调试时引起的窗口重绘等。

尤其是调试时引起的窗口重绘。
但是CPU运转的速度是惊人的,你调试相当于将CPU的速度拖慢了几百万倍,正常运行这些都没问题。
[/Quote]
恩,是这样的,我像你那样子说的,我从新新建了个程序,用你说的,暴力等待,还是不行直接就是返回值有错!这个函数是不是有BUG啊?
hotpos 2012-02-22
  • 打赏
  • 举报
回复
QS_ALLINPUT会使有任何的消息到达消息队列都会结束 MsgWaitForMultipleObjects 的等待,包括键盘、鼠标、以及调试时引起的窗口重绘等。

尤其是调试时引起的窗口重绘。
但是CPU运转的速度是惊人的,你调试相当于将CPU的速度拖慢了几百万倍,正常运行这些都没问题。
longgang521125 2012-02-22
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 hotpos 的回复:]
我习惯暴力等待,就是第三个参数填True,最后个参数填0 ..

这样会在所有线程退出后 MsgWaitForMultipleObjects 才会返回。

你这个不用管它,你在第二个if里面下断点,等有线程退出的时候自然就能断下来
[/Quote]
这样的话,不太好啊,我就不明白了,为什么他一直在第一个if里面!难道工作线程一直不结束?
hotpos 2012-02-22
  • 打赏
  • 举报
回复
我习惯暴力等待,就是第三个参数填True,最后个参数填0 ..

这样会在所有线程退出后 MsgWaitForMultipleObjects 才会返回。

你这个不用管它,你在第二个if里面下断点,等有线程退出的时候自然就能断下来
longgang521125 2012-02-22
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 hotpos 的回复:]
每次都是第一个if是因为唤醒事件QS_ALLINPUT被触发了, QS_ALLINPUT 表示当前线程有任何消息就触发
[/Quote]
那我怎么让线程结束啊?都一直在第一个if里面!怎么跳到第二个if呢?
longgang521125 2012-02-22
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 visualeleven 的回复:]
dRet=::MsgWaitForMultipleObjects(Threadcount,hThreadp,FALSE,INFINITE,QS_ALLINPUT);
if(dRet==WAIT_OBJECT_0+Threadcount)

MsgWaitForMultipleObjects的返回值的范围:WAIT_OBJECT_0 to (WAIT_OBJECT_0 + nCount– 1)……
[/Quote]
不是的吧,第一个是有消息来的时候也会触发好吧!我调试了,都是在第一个if里面!不跳到第二个if里面去根本!
hotpos 2012-02-22
  • 打赏
  • 举报
回复
WAIT_OBJECT_0 + nCount

New input of the type specified in the dwWakeMask parameter is available in the thread's input queue. Functions such as PeekMessage, GetMessage, and WaitMessage mark messages in the queue as old messages. Therefore, after you call one of these functions, a subsequent call to MsgWaitForMultipleObjects will not return until new input of the specified type arrives.
This value is also returned upon the occurrence of a system event that requires the thread's action, such as foreground activation. Therefore, MsgWaitForMultipleObjects can return even though no appropriate input is available and even if dwWakeMask is set to 0. If this occurs, call GetMessage or PeekMessage to process the system event before trying the call to MsgWaitForMultipleObjects again.

怎么不可能成功
Eleven 2012-02-22
  • 打赏
  • 举报
回复
dRet=::MsgWaitForMultipleObjects(Threadcount,hThreadp,FALSE,INFINITE,QS_ALLINPUT);
if(dRet==WAIT_OBJECT_0+Threadcount)

MsgWaitForMultipleObjects的返回值的范围:WAIT_OBJECT_0 to (WAIT_OBJECT_0 + nCount– 1)
你的第一个if判断不可能成功
hotpos 2012-02-22
  • 打赏
  • 举报
回复
每次都是第一个if是因为唤醒事件QS_ALLINPUT被触发了, QS_ALLINPUT 表示当前线程有任何消息就触发
加载更多回复(5)
源码链接: https://pan.quark.cn/s/0f7c75cb3aad ### MIPI Video Mode 与 Command Mode 的差异 #### 一、引言 MIPI (Mobile Industry Processor Interface) 是一种用于连接移动设备中处理器及其外围设备的标准化接口。MIPI 接口支持多种协议,其中包含 DSI (Display Serial Interface) 和 DCS (Display Control Interface) 等协议。在 MIPI 接口的应用中,主要涉及两种工作模式:Video Mode(视频模式)和 Command Mode(命令模式)。本文旨在系统性地阐述这两种模式的工作机制、特性以及实际应用环境。 #### 二、LCD RAM 概念说明 在进一步探讨 MIPI 的两种模式之前,有必要对文中提及的“LCD RAM”概念进行明确。实际上,“LCD RAM”并非一个通用术语,而是本文作者用来描述 LCD 控制器中用于存储显示数据的内存区域。LCD(Liquid Crystal Display,液晶显示屏)通常配备一个控制 IC(Integrated Circuit,集成电路),该控制 IC 可能内置 RAM 以缓存显示数据。 #### 三、MIPI Video Mode(视频模式) **定义:** - 视频模式是一种类似于传统 RGB 接口的工作模式,它要求主机持续不断地向显示器传输刷新数据。 - 在这种模式下,数据和控制信号以报文的形式通过 MIPI 总线进行传输。 - 显示器本身无需配备帧缓冲器,因为主机会周期性地刷新屏幕。 **特点:** 1. **实时性高:** 主机需要不...
源码下载地址: https://pan.quark.cn/s/a4b39357ea24 在电磁模拟技术中,CST(Computer Simulation Technology)是一种被广泛采纳的软件工具,它主要用于电磁场、微波、天线以及射频系统的设计工作。本资料将详细分析CST软件中离散端口的具体配置方法,这些方法对于提升仿真结果的精确度和专业水准具有决定性作用。离散端口在CST软件中扮演着模拟信号输入或输出的重要角色,它们构成了仿真模型不可或缺的部分。在配置离散端口时,一个核心的原则是保证端口的方向与网格线保持一致,这是因为这样做能够有效降低计算过程中产生的误差,并确保仿真数据的有效性。如果未能遵循这一指导原则,可能会引发未知的计算问题,进而导致仿真结果失去可靠性。 在CST软件中配置离散端口,通常需要借助“Pick Points”这一功能。通过选择“Pick Edge Center”选项,端口将被设定在模型边缘的中心位置上。然而,这种做法并不总是能够确保端口与网格线保持平行。在某些特定情形下,模型的几何构造可能不允许直接选取一个与网格线平行的边作为端口的安装位置。 为了克服这一挑战,可以采用多种不同的策略。如果模型本身已经包含一条与馈电口平行的边,那么可以直接利用这条边来建立端口,此时CST软件会自动调整端口使其与网格线对齐。另一种可选的方法是,当模型不具备现成的平行边时,用户可以手动构建一个几何结构,比如一个立方体,并使其边缘与馈电口平行。通过这种方式,新建立的几何结构的边缘就可以作为端口的位置,从而确保端口与网格线的平行关系。 在实施上述操作时,必须关注端口尺寸的合理性和物理意义的一致性。端口的尺寸应当依据实际天线馈电部分的尺寸进行适当调整,过大的端口或...
代码下载链接: https://pan.quark.cn/s/a4b39357ea24 【使用TensorFlow进行图像识别】 图像识别作为计算机视觉领域的关键任务之一,其核心在于通过算法解析和理解图像所包含的信息。在此资源中,我们将集中探讨如何借助功能强大的深度学习框架TensorFlow来执行手写数字识别。手写数字识别构成了众多实际应用的基础,例如自动支票处理、光学字符识别(OCR)等场景。 TensorFlow是由Google创建的一个开源库,它主要用于数值运算和机器学习,尤其在深度学习方面表现卓越。其核心优势在于可以构建并训练复杂的神经网络架构,并且在多种硬件环境中实现高效执行,涵盖CPU和GPU平台。 在此实践项目中,我们将运用TensorFlow来构建一个卷积神经网络(CNN)模型,这种架构是处理图像数据的理想选择。CNNs通过模仿人脑视觉皮层的运作机制,能够自主地提取图像中的关键特征,进而达成识别目标。在手写数字识别的特定情境下,这些特征可能涉及笔画的几何形态、走向以及相互间的连接模式。 对于CNN的基础结构,我们需要具备相应的认知,其通常由卷积层、池化层、全连接层以及激活函数等部分组成。卷积层借助滤波器(亦称卷积核)对图像进行扫描,以捕捉局部特征;池化层则用于降低数据维度,同时保留核心信息;全连接层将特征向量映射至各类别的概率分布;而激活函数如ReLU则通过引入非线性元素,使模型能够学习更为复杂的模式。 在此案例中,建议采用MNIST数据集,这是一个广泛用于手写数字识别的标准测试集。该数据集包含60,000个训练样本和10,000个测试样本,每个样本均为28x28像素的灰度图像,代表0到9这十个数字中的某一个。为了训练模型,必须首先加载数据,并...

15,465

社区成员

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

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