九度企业网站推广软件,石家庄旅游景点,2021年搜索引擎排名,wordpress flash主题采用CreateThread()创建多线程程序
在window环境下#xff0c;Win32 提供了一系列的API函数来完成线程的创建、挂起、恢复、终结以及通信等工作#xff1a;
1、主要的函数列表#xff1a; 序号 函数名 功能 1 CreateThread() 创建一个新线程 2 ExitThread() 正常结…采用CreateThread()创建多线程程序
在window环境下Win32 提供了一系列的API函数来完成线程的创建、挂起、恢复、终结以及通信等工作
1、主要的函数列表 序号 函数名 功能 1 CreateThread() 创建一个新线程 2 ExitThread() 正常结束一个线程的执行 3 TerminateThead() 强制终止一个线程的执行 4 ResumeThread() 重启一个线程 5 SuspendThread() 挂起一个线程 6 GetExiCodeThread() 得到一个线程的退出码 7 GetThreadPriority() 得到一个线程的优先级 8 SetThreadPriority() 设置一个线程的优先级 9 CloseHandle() 关闭一个线程的句柄 10 CreateRemoteThread() 再另一个进程中创建一个新线程 11 PostThreadMessage() 发送一条消息给指定的线程 12 GetCurrentThread() 得到当前的线程句柄 13 GetCurrentThreadId() 得到当前线程的ID 14 GetThreadId() 得到指定线程的ID 15 WaitForSingleObject() 等待单个对象 16 WaitForMultipleObjects() 等待多个对象
关于多线程的API函数还有很多以上只是列出了一些比较常用的函数欲知更多函数和函数的使用方法请参考MSDN或网络资源在此就不再介绍了。
2、线程函数的定义
线程函数的规范格式定义为
DWORD WINAPI ThreadProc (LPVOID lpParam);//格式不正确将无法调用成功。函数名称没有限制只要符合命名规则就可以。
但我常常看到有下列的线程函数定义
void ThreadProc ();//该格式也是可以的但使用的时候要这样通过
LPTHREAD_START_ROUTINE转换如
(LPTHREAD_START_ROUTINE)ThreadProc
我建议还是使用规范的格式比较好不推荐使用void ThreadProc ()格式。不信就请看看MSDN的说明吧
Do not declare this callback function with avoid return typeand cast the function pointer to LPTHREAD_START_ROUTINE when creatingthe thread. Code that does this is common, but it can crash on 64-bit Windows.
而且线程函数必须是全局函数不能在类中声明和定义。
3、多线程实例1
我在此将写一个简单的多线程程序用以展示多线程的功能和使用方法。该程序的主要的思想是画3个进度条分别以多线程和单线程方式完成大家可以比较一下。
说明
1该程序还将和单线程做对比。
2由于给线程的函数传递了多个参数所以采用结构体的方式传递参数。
3为了演示效果采用了比较耗时的打点处理。
主要的函数如下
在头文件的定义 [cpp] view plain copy print ? //线程函数声明 DWORD WINAPI ThreadProc(LPVOIDlpParam); //为了传递多个参数我采用结构体 struct threadInfo { HWND hWnd; //窗口句柄 int nOffset; //偏移量 COLORREF clrRGB; //颜色 }; protected: HANDLE hThead[3]; //用于存储线程句柄 DWORD dwThreadID[3];//用于存储线程的ID threadInfo Info[3]; //传递给线程处理函数的参数 //线程函数声明
DWORD WINAPI ThreadProc(LPVOIDlpParam);
//为了传递多个参数我采用结构体
struct threadInfo
{
HWND hWnd; //窗口句柄
int nOffset; //偏移量
COLORREF clrRGB; //颜色
};
protected:
HANDLE hThead[3]; //用于存储线程句柄
DWORD dwThreadID[3];//用于存储线程的ID
threadInfo Info[3]; //传递给线程处理函数的参数 //实现文件中 [cpp] view plain copy print ? //单线程测试 void CMultiThread_1Dlg::OnBnClickedButton1() { // TODO: 在此添加控件通知处理程序代码 //使能按钮 GetDlgItem(IDC_BUTTON1)-EnableWindow(FALSE); GetDlgItem(IDC_BUTTON2)-EnableWindow(FALSE); CDC *dc GetDC(); CRect rt; GetClientRect(rt); dc-FillSolidRect(0,0,rt.Width(),rt.Height()-70,RGB(240,240,240));//刷新背景 dc-TextOut(97,470,#1); dc-TextOut(297,470,#2); dc-TextOut(497,470,#3); //#1 for (int i0;i460;i) { for (int j 10 ;j200;j) { dc-SetPixel(j,460-i,RGB(255,0,0)); } } //#2 for (int i0;i460;i) { for (int j 210 ;j400;j) { dc-SetPixel(j,460-i,RGB(0,255,0)); } } //#3 for (int i0;i460;i) { for (int j 410 ;j600;j) { dc-SetPixel(j,460-i,RGB(0,0,255)); } } ReleaseDC(dc); //使能按钮 GetDlgItem(IDC_BUTTON1)-EnableWindow(TRUE); GetDlgItem(IDC_BUTTON2)-EnableWindow(TRUE); } //多线程测试 void CMultiThread_1Dlg::OnBnClickedButton2() { // TODO: 在此添加控件通知处理程序代码 CDC *dc GetDC(); CRect rt; GetClientRect(rt); dc-FillSolidRect(0,0,rt.Width(),rt.Height()-70,RGB(240,240,240));//刷新背景 dc-TextOut(97,470,#1); dc-TextOut(297,470,#2); dc-TextOut(497,470,#3); //初始化线程的参数 Info[0].hWnd Info[1].hWnd Info[2].hWnd GetSafeHwnd(); Info[0].nOffset 10;Info[1].nOffset 210;Info[2].nOffset 410; Info[0].clrRGB RGB(255,0,0);Info[1].clrRGB RGB(0,255,0);Info[2].clrRGB RGB(0,0,255); //创建线程 for (int i 0;i3;i) { hThead[i] CreateThread(NULL,0,ThreadProc,Info[i],0,dwThreadID[i]); } ReleaseDC(dc); } DWORD WINAPI ThreadProc(LPVOIDlpParam) { threadInfo*Info (threadInfo*)lpParam; CDC *dc CWnd::FromHandle(Info-hWnd)-GetDC(); for (int i0;i460;i) { for (int jInfo-nOffset;jInfo-nOffset190;j) { dc-SetPixel(j,460-i,Info-clrRGB); } } DeleteObject(dc); return 0; } //单线程测试
void CMultiThread_1Dlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
//使能按钮
GetDlgItem(IDC_BUTTON1)-EnableWindow(FALSE);
GetDlgItem(IDC_BUTTON2)-EnableWindow(FALSE);
CDC *dc GetDC();
CRect rt;
GetClientRect(rt);
dc-FillSolidRect(0,0,rt.Width(),rt.Height()-70,RGB(240,240,240));//刷新背景
dc-TextOut(97,470,#1);
dc-TextOut(297,470,#2);
dc-TextOut(497,470,#3);
//#1
for (int i0;i460;i)
{
for (int j 10 ;j200;j)
{
dc-SetPixel(j,460-i,RGB(255,0,0));
}
}
//#2
for (int i0;i460;i)
{
for (int j 210 ;j400;j)
{
dc-SetPixel(j,460-i,RGB(0,255,0));
}
}
//#3
for (int i0;i460;i)
{
for (int j 410 ;j600;j)
{
dc-SetPixel(j,460-i,RGB(0,0,255));
}
}
ReleaseDC(dc);
//使能按钮
GetDlgItem(IDC_BUTTON1)-EnableWindow(TRUE);
GetDlgItem(IDC_BUTTON2)-EnableWindow(TRUE);
}
//多线程测试
void CMultiThread_1Dlg::OnBnClickedButton2()
{
// TODO: 在此添加控件通知处理程序代码
CDC *dc GetDC();
CRect rt;
GetClientRect(rt);
dc-FillSolidRect(0,0,rt.Width(),rt.Height()-70,RGB(240,240,240));//刷新背景
dc-TextOut(97,470,#1);
dc-TextOut(297,470,#2);
dc-TextOut(497,470,#3);
//初始化线程的参数
Info[0].hWnd Info[1].hWnd Info[2].hWnd GetSafeHwnd();
Info[0].nOffset 10;Info[1].nOffset 210;Info[2].nOffset 410;
Info[0].clrRGB RGB(255,0,0);Info[1].clrRGB RGB(0,255,0);Info[2].clrRGB RGB(0,0,255);
//创建线程
for (int i 0;i3;i)
{
hThead[i] CreateThread(NULL,0,ThreadProc,Info[i],0,dwThreadID[i]);
}
ReleaseDC(dc);
}
DWORD WINAPI ThreadProc(LPVOIDlpParam)
{
threadInfo*Info (threadInfo*)lpParam;
CDC *dc CWnd::FromHandle(Info-hWnd)-GetDC();
for (int i0;i460;i)
{
for (int jInfo-nOffset;jInfo-nOffset190;j)
{
dc-SetPixel(j,460-i,Info-clrRGB);
}
}
DeleteObject(dc);
return 0;
} 运行效果 单线程测试 多线程测试
工程源码下载地址
http://download.csdn.net/detail/cbnotes/4857152
欢迎大家修改和指正。
注意事项
1传递给线程执行函数的参数不能是局部变量而且必须是参数的地址。如
Int nOffset 10;
CreateThread(NULL,0,ThreadProc,nOffset,0,dwThreadID[i]);//错误
CreateThread(NULL,0,ThreadProc,nOffset,0,dwThreadID[i]);//错误
Int *pOffset newint(10);
CreateThread(NULL,0,ThreadProc,pOffset,0,dwThreadID[i]);//正确
2线程执行函数必须是全局函数。
3请大家改改下面的程序且解释下为什么
这是我开始写程序遇到的一个问题
改写上面的函数只是将结构体中一个参数改为CDC指针以便直接调用。
structthreadInfo
{ CDC * dc; //画布 int nOffset; //偏移量 COLORREFclrRGB; //颜色
};
//多线程测试
voidCMultiThread_1Dlg::OnBnClickedButton2()
{ // TODO:在此添加控件通知处理程序代码 CDC *dc GetDC(); CRectrt; GetClientRect(rt); dc-FillSolidRect(0,0,rt.Width(),rt.Height()-70,RGB(240,240,240));//刷新背景 dc-TextOut(97,470,#1); dc-TextOut(297,470,#2); dc-TextOut(497,470,#3); //初始化线程的参数 Info[0].dc Info[1]dc Info[2].dc dc; Info[0].nOffset 10;Info[1].nOffset 210;Info[2].nOffset 410; Info[0].clrRGB RGB(255,0,0);Info[1].clrRGBRGB(0,255,0);Info[2].clrRGB RGB(0,0,255); //创建线程 for (inti 0;i3;i) { hThead[i] CreateThread(NULL,0,ThreadProc,Info[i],0,dwThreadID[i]); } //ReleaseDC(dc);
}
//线程执行函数
DWORDWINAPI ThreadProc(LPVOIDlpParam)
{ threadInfo*Info (threadInfo*)lpParam; for (inti0;i460;i) { for (intjInfo-nOffset;jInfo-nOffset190;j) { Info-dc-SetPixel(j,460-i,Info-clrRGB); } } return 0;
}
运行结果 为什么会这样呢我还没有找到答案望大家能给我个解释谢谢。 4、多线程实例2
该实例将演示一个简单的多线程协同工作的例子以供大家学习和参考。大致原理是5个人开始比赛比如赛跑谁先完成比赛就结束并统比赛时间和赢者。主线程用于界面的相关显示5个线程模拟5个人的行为赛跑另外一个线程用于检测5个线程的运行情况只要有人到达终点比赛就结束并做相关的技术统计。
主要函数为 MulitThread_2Dlg.h : 头文件
//声明线程处理函数
DWORDWINAPI ThreadProc1(LPVOIDlpParam);
DWORDWINAPI ThreadProc2(LPVOIDlpParam);
//为了传递多个参数我采用结构体
structthreadInfo1
{ HWNDhWnd; //窗口句柄 int nOffset; //偏移量
}; structthreadInfo2
{ HWNDhWnd; //窗口句柄 HANDLE *phHandle; //偏移量
};
protected: long m_nTime;//时间 HANDLEm_hThead[5]; //用于存储线程句柄 HANDLEhThead; //用于存储线程句柄 DWORD m_dwThreadID[5];//用于存储线程的ID threadInfo1Info1[5]; //传递给线程处理函数的参数 threadInfo2Info2; // MulitThread_2Dlg.cpp : 实现文件
//更新时间毫秒
voidCMulitThread_2Dlg::OnTimer(UINT_PTRnIDEvent)
{ // TODO:在此添加消息处理程序代码和/或调用默认值 m_nTime100;//毫秒为单位 CStringstr; str.Format(时间%.1f秒,m_nTime/1000.0); GetDlgItem(IDC_STATIC2)-SetWindowText(str); CDialog::OnTimer(nIDEvent);
} //消息处理函数
LRESULTCMulitThread_2Dlg::OnGameOver(WPARAMwParam,LPARAMlParam)
{ KillTimer(1);//关闭计时器 if (wParam 0) {//出错 GetDlgItem(IDC_STATIC1)-SetWindowText(出错啦!); GetDlgItem(IDC_STATIC2)-SetWindowText(---); AfxMessageBox(出错啦!,MB_OK|MB_ICONERROR); } else {//成功 //显示结果 char *pName[] {张三,李四,王二,小蔡,赵干}; CStringstr; str.Format(赢者%s,pName[lParam]); GetDlgItem(IDC_STATIC1)-SetWindowText(str); } //使能开始按钮以便可以开始下一次比赛 GetDlgItem(IDC_BUTTON1)-EnableWindow(TRUE); return 0;
} //开始比赛
voidCMulitThread_2Dlg::OnBnClickedButton1()
{ // TODO:在此添加控件通知处理程序代码 //使能开始按钮无效 GetDlgItem(IDC_BUTTON1)-EnableWindow(FALSE); m_nTime 0;//初始化时间为 CDC *dc GetDC(); CRectrt; GetClientRect(rt); dc-FillSolidRect(40,0,rt.Width()-49,rt.Height()-50,RGB(240,240,240));//刷新背景 ReleaseDC(dc); //初始化线程的参数 Info1[0].hWnd Info1[1].hWnd Info1[2].hWnd Info1[3].hWnd Info1[4].hWnd GetSafeHwnd(); Info1[0].nOffset 0;Info1[1].nOffset 90;Info1[2].nOffset 180;Info1[3].nOffset 270;Info1[4].nOffset 360; //创建线程 for (inti 0;i5;i) { m_hThead[i] CreateThread(NULL,0,ThreadProc1,Info1[i],CREATE_SUSPENDED,m_dwThreadID[i]); } SetTimer(1,100,NULL);//开始计时 GetDlgItem(IDC_STATIC1)-SetWindowText(进行中...); //开始运行 for (inti 0;i5;i) { ResumeThread(m_hThead[i]); } //开始运行监测结果线程 Info2.hWnd m_hWnd; Info2.phHandle m_hThead; hThead CreateThread(NULL,0,ThreadProc2,Info2,0,NULL);
} //比赛线程
DWORDWINAPI ThreadProc1(LPVOIDlpParam)
{ threadInfo1*info (threadInfo1*)lpParam; CDC *dc CWnd::FromHandle(info-hWnd)-GetDC(); for (inti40;i570;i2) { for (intj0;j1000;j) {//重复操作以便人眼观察 dc-Rectangle(CRect(i,info-nOffset,i1,info-nOffset80)); } } DeleteObject(dc); return 0;
} //监视线程谁先完成比赛就结束
DWORDWINAPI ThreadProc2(LPVOIDlpParam)
{ threadInfo2*info (threadInfo2*)lpParam; DWORDdwRet 0; //等待个线程中的一个完成 dwRet WaitForMultipleObjects(5,info-phHandle,FALSE,INFINITE); if (dwRet WAIT_FAILED) {//出错啦 ::SendMessage(info-hWnd,WM_GAMEOVER,0,0); return 0; } //终止各个线程 for (inti0;i5;i) { TerminateThread(info-phHandle[i],0); } //发送比赛结果消息 ::SendMessage(info-hWnd,WM_GAMEOVER,1,dwRet-WAIT_OBJECT_0); return 0;
} 运行结果 工程源码下载地址
http://download.csdn.net/detail/cbnotes/4867333
欢迎大家修改和指正。
注意事项
1. 该程序连主线程一共7个线程。其中一个线程专门用于检测5个比赛线程的运行结果检测为什么要专门开这个线程而不在主线程中进行呢主要是WaitForMultipleObjects()函数是一个阻塞函数如果在主线程中运行该函数将使整个程序的界面不能操作如不能移动窗口等因为一直阻塞在WaitForMultipleObjects函数处而不能处理其它消息不信大家可以试试。
2. 线程同步的两个比较重要的函数为WaitForSingleObject()和WaitForMultipleObjects()具体使用请参考MSDN。这两个函数都是阻塞函数一直等待授信的对象发生才返回。
3. 采用消息的方式通知主线程的运行结果该方法比较简单有效。一般的多线程程序都是采用主线程负责显示辅助线程来完成比较耗时的任务等任务完成后再通知主线程运行结果。