广州十大网站开发公司,天津建设厅网站,网站推广的定义,网络黄页推广软件下载InterlockedIncrement 
函数的作用#xff1a; 
在多线程同时对一个变量访问时#xff0c;保证一个线程访问变量时其他线程不能访问 
事件是很常用的多线程同步互斥机制 
HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, // SECURITY_ATTRIBUTES结构指针…InterlockedIncrement 
函数的作用 
在多线程同时对一个变量访问时保证一个线程访问变量时其他线程不能访问 
事件是很常用的多线程同步互斥机制 
HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, // SECURITY_ATTRIBUTES结构指针可为NULLBOOL bManualReset,     // 手动/自动// TRUE表示手动在WaitForSingleObject后必须手动调用ResetEvent清除信号// FALSE表示自动在WaitForSingleObject后系统自动清除事件信号BOOL bInitialState,        //初始状态FALSE为无信号TRUE为有信号LPCTSTR lpName         //事件的名称);下边是使用演示  CreateThread 
采用CreateThread()创建多线程程序参考https://blog.csdn.net/cbnotes/article/details/8277180/多线程实例 
在此将写一个简单的多线程程序用以展示多线程的功能和使用方法。该程序的主要的思想是画3个进度条分别以多线程和单线程方式完成大家可以比较一下。 
说明 
1该程序还将和单线程做对比。 
2由于给线程的函数传递了多个参数所以采用结构体的方式传递参数。 
3为了演示效果采用了比较耗时的打点处理。 
//线程函数声明
DWORD WINAPI ThreadProc(LPVOIDlpParam);
//为了传递多个参数我采用结构体
struct threadInfo
{HWND hWnd;       //窗口句柄int  nOffset;    //偏移量COLORREF clrRGB; //颜色
};protected:
HANDLE hThead[3];    //用于存储线程句柄DWORD  dwThreadID[3];//用于存储线程的IDthreadInfo Info[3];   //传递给线程处理函数的参数//---- 代码实现//单线程测试
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);//#1for (int i0;i460;i){for (int j 10 ;j200;j){dc-SetPixel(j,460-i,RGB(255,0,0));}}//#2for (int i0;i460;i){for (int j 210 ;j400;j){dc-SetPixel(j,460-i,RGB(0,255,0));}}//#3for (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;
}测试效果如下   
GetMessage 
GetMessage是从调用线程的消息队列里取得一个消息并将其放于指定的结构。此函数可取得与指定窗口联系的消息和由PostThreadMessage寄送的线程消息。此函数接收一定范围的消息值。GetMessage不接收属于其他线程或应用程序的消息。获取消息成功后线程将从消息队列中删除该消息。函数会一直等待直到有消息到来才有返回值。GetMessageLPMSG lpMsgHWND hWndUINT wMsgFilterMinUINT wMsgFilterMax 
参数
lpMsg指向MSG结构的指针该结构从线程的消息队列里接收消息信息。
hWnd取得其消息的窗口的句柄。当其值取NULL时GetMessage为任何属于调用线程的窗口检索消息线程消息通过PostThreadMessage寄送给调用线程。
wMsgFilterMin指定被检索的最小消息值的整数。
wMsgFilterMax指定被检索的最大消息值的整数。
返回值如果函数取得WM_QUIT之外的其他消息返回非零值。如果函数取得WM_QUIT消息返回值是零。如果出现了错误返回值是-1。例如当hWnd是无效的窗口句柄或lpMsg是无效的指针时。若想获得更多   的错误信息请调用GetLastError函数。PeekMessage 
PeekMessage 调用的一个例子 
PeekMessage(msg,NULL,0,0,PM_REMOVE);前面的4个参数一个指向 MSG 结构的指针、一个窗口的句柄、两个值指示消息范围与 GetMessage 的参数相同。 将第二、三、四个参数设置为 NULL 或 0时表明我们想让 PeekMessage 返回程序中所有窗口的所有消息。 
如果要将消息从消息队列中删除则将 PeekMessage 的最后一个参数设置为 PM_REMOVE。 如果不希望删除消息则将最后一个参数设置为 PM_NOREMOVE这使得程序可以检查程序的消息队列中的下一个消息而不实际删除它。 
GetMessage 不将控制返回给程序直到从程序的消息队列中获取消息但是 PeekMessage 总是立刻返回而不论一个消息是否出现。 当应用程序的消息队列中有一个消息时PeekMessage 的返回值为 TRUE(非0)并且将按通常方式处理消息。当队列中没有消息时PeekMessage 返回 FALSE(0)。 考虑如下例子 
// 普通的消息循环 
while( GetMessage(msg,NULL,0,0) )
{TranslateMessage(msg);DispatchMessage (msg);
}
return msg.wParam;// 等价于
while( TRUE )
{if( PeekMessage(msg,NULL,0,0,PM_REMOVE) ){if(msg.message  WM_QUIT){break;}TranslateMessage(msg);DispatchMessage(msg);}else{// Other program lines to do some work}
}
return msg.wParam;如果 PeekMessage 的返回值为 TRUE,则消息按通常方式进行处理。如果返回值为 FALSE,则在将控制返回给Windows操作系统 之前还可以做一点工作如显示另一个随机矩形。 
PeekMessage 不能从消息队列中删除 WM_PAINT 消息。 从队列中删除 WM_PAINT 消息的唯一方法是令窗口客户区的失效区域变得有效这可以用 ValidateRect 和 ValidateRgn 或者 BeginPaint 和 EndPaint 对来完成。 
不能使用如下所示的代码来清除消息队列中的所有消息 while( PeekMessage(msg,NULL,0,0,PM_REMOVE) ); 这条语句从消息队列中删除 WM_PAINT 之外的所有消息。如果队列中有一个 WM_PAINT 消息程序就会永远地陷在 while 循环中。 
WaitForSingleObject 
等待函数可使线程自愿进入等待状态直到一个特定的内核对象变为已通知状态为止 
DWORD WaitForSingleObject(HANDLE hObject, DWORD dwMilliseconds);当线程调用该函数时第一个参数hObject标识一个能够支持被通知/未通知的内核对象。第二个参数dwMilliseconds.允许该线程指明为了等待该对象变为已通知状态它将等待多长时间。 
调用下面这个函数将告诉系统调用函数准备等待到hProcess句柄标识的进程终止运行为止 
WaitForSingleObject(hProcess, INFINITE);第二个参数告诉系统调用线程愿意永远等待下去无限时间量直到该进程终止运行。 通常情况下 INFINITE是作为第二个参数传递给WaitForSingleObject的不过也可以传递任何一个值以毫秒计算。顺便说一下 INFINITE已经定义为0xFFFFFFFF或-1。当然传递INFINITE有些危险。如果对象永远不变为已通知状态那么调用线程永远不会被唤醒它将永远处于死锁状态 不过它不会浪费宝贵的CPU时间。 
下面是如何用一个超时值而不是INFINITE来调用WaitForSingleObject的例子 
DWORD dw  WaitForSingleObject(hProcess, 5000);
switch(dw)
{case WAIT_OBJECT_0:// The process terminated.break;case WAIT_TIMEOUT:// The process did not terminate within 5000 milliseconds.break;case WAIT_FAILED:// Bad call to function (invalid handle?)break;
}上面这个代码告诉系统在特定的进程终止运行之前或者在5 0 0 0 m s时间结束之前调用线程不应该变为可调度状态。因此如果进程终止运行那么这个 函数调用将在不到5000ms的时间内返回如果进程尚未终止运行那么它在大约5000ms时间内返回。注意不能为dwMilliseconds传递0。如果传递了0WaitForSingleObject函数将总是立即返回。WaitForSingleObject的返回值能够指明调用线程为什么再次变为可调度状态。如果线程等待的对象变为已通知状态那么返回值是WAIT_OBJECT_0。如果设置的超时已经到期则返回值是WAIT_TIMEOUT。如果将一个错误的值如一个无效句柄传递给WaitForSingleObject那么返回值将是WAIT_FAILED若要了解详细信息可调用GetLastError。