线程的创建-基于MFC对话框-基础②

多抽出一分钟学习,让你的生命更加精彩

理解多线程的好处
在上篇文章中,我们的主线程即按键点击响应函数,如果我们在响应函数中加入睡眠函数(可以理解为正在联网或者其他某种读取信息的状态),再对对话框做其他操作,程序就会出现卡死的情况,但是如果我们将睡眠函数放入分线程中(理解为我们把联网等待等操作放入分线程),执行程序则不会卡死,后台的分线程执行阻塞的操作,主线程(主线程指主对话框不关闭时一直循环取响应函数的过程)不会受到任何影响,这就是多线程的好处。test代码如下:
在这里插入图片描述
如何测试线程是否运行
我们在百度上花一秒钟下载DebugView软件,之后打开监视,运行如下进程(主线程是点击函数,其子线程为ThreadProc),程序一直在执行,且对对话框进行其他操作,并不会出现卡死的情况,用眼睛真正看到了多线程在执行,代码如下(.cpp文件插入点击函数和线程函数):

UINT _cdecl ThreadProc(LPVOID lpParameter) 
{
 int tipMsg = (int)lpParameter;//将指针类型强转为int
 CString strTipMsg;
 while (TRUE)
 {
  strTipMsg.Format(_T("num = %d"), tipMsg++);//将int类型转换为CString类型(MFC字符串)
  OutputDebugString(strTipMsg);//微软打印输出字符串API,只有一个参数
  Sleep(50);//每打印一个输出暂停50ms
 }
 return 0;
}

void C多线程Dlg::OnBnClickedBtn()
{
//  TODO: 在此添加控件通知处理程序代码
// DWORD dwThreadID = 0;
// HANDLE hThread = CreateThread(NULL, 0, ThreadProc, (LPVOID)123, 0,&dwThreadID);//线程函数的参数要是指针类型,我们强转一下即可
// CloseHandle(hThread);//主线程不需要此线程时,要释放资源,不释放会导致内存泄漏。
 CWinThread *pThread = AfxBeginThread(ThreadProc,(LPVOID)100);
}

运行结果截图:
在这里插入图片描述
如果想用主对话框中的元素,则可以选主对话框类的指针作为线程参数即传递this指针即可。
如void C多线程Dlg::OnBnClickedBtn()这个函数当前所在作用域的类是C多线程Dlg即主对话框类。
在.h文件中定义一个int m_Num;
同时.cpp的代码如下:

UINT _cdecl  ThreadProc(LPVOID lpParameter) 
{
 C多线程Dlg *pThisDlg = (C多线程Dlg *)lpParameter;//获取当前主对话框的指针,要进行强转
 int tipMsg = pThisDlg->m_Num;//获取主对话框的成员
 CString strTipMsg;
 while (TRUE)
 {
  strTipMsg.Format(_T("num = %d"), tipMsg++);//将int类型转换为CString类型(MFC字符串)
  OutputDebugString(strTipMsg);//微软打印输出字符串API,只有一个参数
  Sleep(50);//每打印一个输出暂停50ms
 }
 return 0;
}

void C多线程Dlg::OnBnClickedBtn()
{
_Num = 123;
 CWinThread *pThread = AfxBeginThread(ThreadProc,this);
}

线程函数即可调用了主对话框里面的成员变量。

如果实在要想让线程函数做主对话框的成员函数如何实现?
在.h文件中声明线程函数的时候前面加上static即可,如:
在这里插入图片描述
同时要在.cpp文件中对线程函数进行作用域的声明:

UINT _cdecl  C多线程Dlg::ThreadProc(LPVOID lpParameter) 
{
}

注意:该成员函数不能直接引用成员变量m_Num,因为
静态成员函数(即该线程函数)是不能直接引用成员变量的,其作用域是整个类,并不是当前类的对象,没有this指针,因此需要将主对话框的this指针通过参数传递过来。 剩下的代码不变,即可将线程函数变为成员函数。

猜你喜欢

转载自blog.csdn.net/qq_42308217/article/details/108415171