源代码下载:http://www.vckbase.com/code/downcode.asp?id=2975
相关文章:http://www.vckbase.com/document/viewdoc/?id=1706建立一个基于对话框的工程MultiThread5,在对话框IDD_MULTITHREAD5_DIALOG中加入一个编辑框IDC_MILLISECOND,一个按钮IDC_START,标题为“开始” ,一个进度条IDC_PROGRESS1;
打开ClassWizard,为编辑框IDC_MILLISECOND添加int型变量m_nMilliSecond,为进度条IDC_PROGRESS1添加CProgressCtrl型变量m_ctrlProgress;
在MultiThread5Dlg.h文件中添加一个结构的定义:
struct threadInfo
{
UINT nMilliSecond;
CProgressCtrl* pctrlProgress;
};线程函数的声明:UINT ThreadFunc(LPVOID lpParam);
注意,二者应在类CMultiThread5Dlg的外部。在类CMultiThread5Dlg内部添加protected型变量:CWinThread* pThread;
在MultiThread5Dlg.cpp文件中进行如下操作:定义公共变量:threadInfo Info;
双击按钮IDC_START,添加相应消息处理函数:void CMultiThread5Dlg::OnStart()
{
// TODO: Add your control notification handler code here UpdateData(TRUE);
Info.nMilliSecond=m_nMilliSecond;
Info.pctrlProgress=&m_ctrlProgress; pThread=AfxBeginThread(ThreadFunc,
&Info);
}在函数BOOL CMultiThread3Dlg::OnInitDialog()中添加语句:
{
……
// TODO: Add extra initialization here
m_ctrlProgress.SetRange(0,99);
m_nMilliSecond=10;
UpdateData(FALSE);
return TRUE; // return TRUE unless you set the focus to a control
}添加线程处理函数:
UINT ThreadFunc(LPVOID lpParam)
{
threadInfo* pInfo=(threadInfo*)lpParam;
for(int i=0;i<100;i++)
{
int nTemp=pInfo->nMilliSecond; pInfo->pctrlProgress->SetPos(i); Sleep(nTemp);
}
return 0;
}当线程正在运行时点击右上角的关闭按钮,然后查看输出窗口得到下面的内容:
线程 'Win32 线程' (0xc8c) 已退出,返回值为 2 (0x2)。
线程 'Win32 线程' (0x514) 已退出,返回值为 2 (0x2)。
Detected memory leaks!
Dumping objects ->
f:\rtm\vctools\vc7libs\ship\atlmfc\src\mfc\thrdcore.cpp(306) : {97} client block at 0x003A7778, subtype c0, 68 bytes long.
a CWinThread object at $003A7778, 68 bytes long
Object dump complete.程序“[1740] MultiThread5.exe: 本机”已退出,返回值为 2 (0x2)。红色部分为内存泄露信息
暂且不说有没有必要避免这个问题,我想知道有什么办法解决这个问题。
相关文章:http://www.vckbase.com/document/viewdoc/?id=1706建立一个基于对话框的工程MultiThread5,在对话框IDD_MULTITHREAD5_DIALOG中加入一个编辑框IDC_MILLISECOND,一个按钮IDC_START,标题为“开始” ,一个进度条IDC_PROGRESS1;
打开ClassWizard,为编辑框IDC_MILLISECOND添加int型变量m_nMilliSecond,为进度条IDC_PROGRESS1添加CProgressCtrl型变量m_ctrlProgress;
在MultiThread5Dlg.h文件中添加一个结构的定义:
struct threadInfo
{
UINT nMilliSecond;
CProgressCtrl* pctrlProgress;
};线程函数的声明:UINT ThreadFunc(LPVOID lpParam);
注意,二者应在类CMultiThread5Dlg的外部。在类CMultiThread5Dlg内部添加protected型变量:CWinThread* pThread;
在MultiThread5Dlg.cpp文件中进行如下操作:定义公共变量:threadInfo Info;
双击按钮IDC_START,添加相应消息处理函数:void CMultiThread5Dlg::OnStart()
{
// TODO: Add your control notification handler code here UpdateData(TRUE);
Info.nMilliSecond=m_nMilliSecond;
Info.pctrlProgress=&m_ctrlProgress; pThread=AfxBeginThread(ThreadFunc,
&Info);
}在函数BOOL CMultiThread3Dlg::OnInitDialog()中添加语句:
{
……
// TODO: Add extra initialization here
m_ctrlProgress.SetRange(0,99);
m_nMilliSecond=10;
UpdateData(FALSE);
return TRUE; // return TRUE unless you set the focus to a control
}添加线程处理函数:
UINT ThreadFunc(LPVOID lpParam)
{
threadInfo* pInfo=(threadInfo*)lpParam;
for(int i=0;i<100;i++)
{
int nTemp=pInfo->nMilliSecond; pInfo->pctrlProgress->SetPos(i); Sleep(nTemp);
}
return 0;
}当线程正在运行时点击右上角的关闭按钮,然后查看输出窗口得到下面的内容:
线程 'Win32 线程' (0xc8c) 已退出,返回值为 2 (0x2)。
线程 'Win32 线程' (0x514) 已退出,返回值为 2 (0x2)。
Detected memory leaks!
Dumping objects ->
f:\rtm\vctools\vc7libs\ship\atlmfc\src\mfc\thrdcore.cpp(306) : {97} client block at 0x003A7778, subtype c0, 68 bytes long.
a CWinThread object at $003A7778, 68 bytes long
Object dump complete.程序“[1740] MultiThread5.exe: 本机”已退出,返回值为 2 (0x2)。红色部分为内存泄露信息
暂且不说有没有必要避免这个问题,我想知道有什么办法解决这个问题。
while(1)
{
......
......
Sleep(2000);//当我的程序要退出时刚好运行到这句,那么主程序怎么才能知道这个线程结束?
....
}
换句话说,当线程正在运行时,我要退出程序,怎么才可以安全的退出。
for循环里写个Bool变量标记是否继续循环
外部设置这个变量 然后用定时器等待线程退出即可
不要在UI线程里WaitForSingleObject无限等待!
其次:每个子线程必须不阻塞超过太长时间,例如500ms它必须检查这个标志一次
再次:主线程应该用WaitForSingleObject等待子线程退出
参考Jeffrey Richter 的处理模式
可以用全局变量或者事件对象。在线程里如果检测到这个全局变量置为标志退出的值或者事件对象为有信号状态,就return。
还有不要在线程里如下更新主线程界面 pInfo->pctrlProgress->SetPos(i);
而要通过给主窗口寄送消息的方式,让主窗口自己来更新。
{
DWORD dwTickstart = GetTickCount();
while(!bStop)
{
if ( (GetTickCount() - dwTickstart) > dwMS)
{
break;
} Sleep(1);
}
}线程一般自然退出最好. 强制退出非必要不要使用, 可以用如下代码: m_bStopThread为线程死循环的变量,
m_pThread为线程指针. m_bStopThread = TRUE; while (m_pThread != NULL)
{
MSG msg;
if(PeekMessage(&msg, m_hWnd, 0, 0, PM_NOREMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
} Sleep(30);
}
不过其它资源就难说了,比如某某设备等
{
break;
}
while(1)
{
......
......
Sleep(2000);//当我的程序要退出时刚好运行到这句,那么主程序怎么才能知道这个线程结束?
....
}
当我的程序要退出时刚好运行到这句,那么主程序怎么才能知道这个线程结束?
大家注意看我这句话,我退出程序的时候刚好运行到Sleep(2000)这句,怎么办?但是退出时主程序并不知道运行到哪句了。
我既然用了Sleep(2000)就不存在优化之类的说法了,例如我写个定时器,两秒检测一下,你给我改成Sleep(1)我程序就没法用了是吧。
汗, 我的意思是你用mf_Sleep(2000, bStop); 来代替 Sleep(2000);
并在主线程中用WaitForSingleObject等待线程句柄等线程自己退出后再结束主线程
优点:安全、逻辑清晰、适用于多线程处理复杂的业务逻辑、很方便支持线程消息
缺点:资源开销偏大(其实也大不了多少)【二】工作线程的话,如果是纯粹的循环业务处理的工作线程,可以再每次循环的入口或者业务间隙点里增加一个型号对象(一般用Event),如果要退出此线程(循环操作),在任何地方SetEvent一下就行了,当事件触发后,就会跳出循环了。
优点:占用资源少
缺点:一般工作线程是处理一些独立的业务,交互性较差(相对)【总结】
不管是工作线程还是UI线程最后退出的时候,都尽量做到用WaitForSingleObject来判断线程对象是否已经退出,超时时间不能是永久,一般是根据具体的业务析构的复杂度来自己判定……************************************************************************************
以上只是个人的一些经验谈,不一定一定对,呵呵!
相互学习……
void CPRRAlarmNotificationDlg::mf_Sleep(DWORD dwMS, const BOOL &bStop)
{
DWORD dwTickstart = GetTickCount();
while(!bStop)
{
if ( (GetTickCount() - dwTickstart) > dwMS)
{
break;
} Sleep(1);
}
}这个不是我给你的代码吗?汗. lz应该仔细看看回复.
用 waitforsingleobject 等待线程句柄释放 , 不能无限等待 , 再用全局变量做后备,
如果线程死或者不知道卡在哪里 , Terminate.至于sleep(2000) , 线程里最好别用.