mfc线程 postmessagee是在主线程中执行吗

&&& 本文将使用C++语言,在MFC框架的配合下给出PostMessage、SendMessage等的使用方式与使用不当造成的后果(讨论均针对自定义的消息进行)。如有什么错误,欢迎指正。
写过Windows程序的同学都知道PostMessage、SendMessage的区别,PostMessage函数调用发送之后,立即返回,不等待消息处理完成。而SendMessage则让调用的线程处于阻塞(BLOCk)状态,直到消息处理完成。
&&&&&&&正由于这两个函数的区别导致了如下想法:
&&&&&&&想法1:PostMessage立即返回,在程序中,处理界面显示(如处理进度条、滚动条等)时使用PostMessage,不会影响程序的用户体验。
&&&&&&&想法2:在程序中全用PostMessage,放弃SendMessage,好处:PostMessage是立即返回的,可以不影响程序的正常流程,就算在消息处理函数中卡死了,也不影响主线程的运行。
&&&&&&&起初&学习&到了这些想法,以为受益匪浅,但经过一段时间之后,发现此两种想法都是不可取的。
&&&&&&&分析想法1:
&&&&&&&这里可分为两点:
1)&&在主线程中Post消息,以处理进度条显示(用WM_MY_TEST的参数WPARAM、LPARAM来处理进度条的显示)
代码:code_1
#define&WM_MY_TEST&(WM_USER&+ 100)
void&CMyDlg::OnBnClickedOk()
&&&&&int&nParam1&= 0;
&&&&&int&nParam2&= 0;
&&&&&for&(int&nIndex&= 0;&nIndex&& 1000;&nIndex++)
&&&&&&&&&// Do other things
&&&&&&&&&//&&
&&&&&&&&&nParam1++;
&&&&&&&&&nParam2++;
&&&&&&&&&PostMessage(WM_MY_TEST, (WPARAM)&nParam1, (LPARAM)&nParam2);
&&&&&//OnOK();
LRESULT&CMyDlg::OnMyTest(WPARAM&wParam,&LPARAM&lParam)
&&&&&static&int&nTimes&= 0;
&&&&&CString&strOutP
&&&&&int*&pParam1&= (int*)wP
&&&&&int*&pParam2&= (int*)lP
&&&&&nTimes++;
&&&&&strOutPut.Format(_T("%s%d&&&%s%d&%s%d"),
&&&&&&&&&_T("Param1 = "), *pParam1,
&&&&&&&&&_T("Param2 = "), *pParam2,
&&&&&&&&&_T("RealTimes = "),&nTimes);
&&&&&OutputDebugString(strOutPut);
&&&&&return&0;
code_1将运行的结果:
Param1 = 0 Param2 = 0 RealTimes = 1
Param1 = 0 Param2 = 0 RealTimes = 2
Param1 = 0 Param2 = 0 RealTimes = 3
Param1 = 0 Param2 = 0 RealTimes = 1000
结果远不如我们所料,表现为PostMessage多次发送时,2~1000的消息参数全被冲掉了。用pParam1、pParam2来处理进度条的话,后果可想而知(进度条根本没动)。如果将上面的PostMessage改为SendMessage,结果如下:
Param1 = 1 Param2 = 1 RealTimes = 1
Param1 = 2 Param2 = 2 RealTimes = 2
Param1 = 3 Param2 = 3 RealTimes = 3
Param1 = 1000 Param2 = 1000 RealTimes = 1000
可见,稳定的输出了需要的内容,可以很好的控制。
在此情况下(主线程中Post消息时),不仅没有改善用户体验,反而更差了。
不可以频繁使用PostMessage发送同一个消息,除非保证上一次发送的消息被处理完成(这如何保证???),这还不如直接用SendMessage。
当然OnMyTest函数可能是这样的:
LRESULT&CMyDlg::OnMyTest(WPARAM&wParam,&LPARAM&lParam)
&&&&&static&int&nTimes&= 0;
&&&&&CString&strOutP
&&&&&int*&pParam1&= (int*)wP
&&&&&int*&pParam2&= (int*)lP
&&&&&nTimes++;
&&&&&strOutPut.Format(_T("%s%d&&&%s%d&%s%d"),
&&&&&&&&&_T("Param1 = "), *pParam1,
&&&&&&&&&_T("Param2 = "), *pParam2,
&&&&&&&&&_T("RealTimes = "),&nTimes);
&&&&&OutputDebugString(strOutPut);
&&&&&//&大量访问网络,磁盘等低速操作
&&&&&return&0;
在这种情况下,如果用SendMessage的话,用户体验将会大大下降,甚至导致程序无法响应。于是有人提出了使用PostMessage,这样程序不会无法响应,最多显示不正确罢了。乍一看,提议似乎还不错,至少程序正常运行了。但是,这些网络访问、磁盘读写等操作为什么要放到界面的代码中呢?界面、代码分离才是合理的,因此可以认定,访问网络、磁盘读写等操作不应该放到这里来处理。
2)&&在非主线程中Post消息,以处理进度条显示(用WM_MY_TEST的参数WPARAM、LPARAM来处理进度条的显示)
代码:code_2
DWORD&WINAPI&ThreadProc(&LPVOID&lpParam&)
&&&&&CMyDlg&*pThis&= (CMyDlg&*)lpP
&&&&&int&nParam1&= 0;
&&&&&int&nParam2&= 0;
&&&&&for&(int&nIndex&= 0;&nIndex&& 1000;&nIndex++)
&&&&&&&&&nParam1++;
&&&&&&&&&nParam2++;
&&&&&&&&&pThis-&PostMessage(WM_MY_TEST, (WPARAM)&(nParam1), (LPARAM)&(nParam2));
&&&&&return&0;
void&CMyDlg::OnBnClickedOk()
&&&&&HANDLE&hThread&=&CreateThread(NULL,
&&&&&&&&&0,
&&&&&&&&&ThreadProc,&
&&&&&&&&&(void*)this,
&&&&&&&&&0,
&&&&&&&&&NULL);
&&&&&//OnOK();
LRESULT&CMyDlg::OnMyTest(WPARAM&wParam,&LPARAM&lParam)
&&&&&static&int&nTimes&= 0;
&&&&&CString&strOutP
&&&&&int*&pParam1&= (int*)wP
&&&&&int*&pParam2&= (int*)lP
&&&&&nTimes++;
&&&&&strOutPut.Format(_T("%s%d&&&%s%d&%s%d"),
&&&&&&&&&_T("Param1 = "), *pParam1,
&&&&&&&&&_T("Param2 = "), *pParam2,
&&&&&&&&&_T("RealTimes = "),&nTimes);
&&&&&OutputDebugString(strOutPut);
&&&&&return&0;
code_2的运行结果:
(程序直接崩溃了)
线程函数不等待WM_MY_TEST的返回,循环1000次之后直接退出了,这导致栈上的变量nParam1、nParam2被释放,然后OnMyTest处理的时候,nParam1、nParam2的地址已经无效了,导致崩溃。SendMessage则不会出现此类情况。
代码:code_2(2)
DWORD&WINAPI&ThreadProc(&LPVOID&lpParam&)
&&&&&CqwerDlg&*pThis&= (CqwerDlg&*)lpP
&&&&&int&*nParam1&=&NULL;
&&&&&int&*nParam2&=&NULL;
&&&&&nParam1&=&new&
&&&&&nParam2&=&new&
&&&&&for&(int&nIndex&= 0;&nIndex&& 1000;&nIndex++)
&&&&&&&&&*nParam1&=&nI
&&&&&&&&&*nParam2&=&nI
&&&&&&&&&pThis-&PostMessage(WM_MY_TEST, (WPARAM)nParam1, (LPARAM)nParam2);
&&&&&return&0;
由于堆内存没有被释放,所以程序没有崩溃,在我的机器上运行结果为:
Param1 = 27 Param2 = 27 RealTimes = 1
Param1 = 117 Param2 = 117 RealTimes = 2
Param1 = 162 Param2 = 162 RealTimes = 3
Param1 = 218 Param2 = 218 RealTimes = 4
Param1 = 272 Param2 = 272 RealTimes = 5
Param1 = 312 Param2 = 312 RealTimes = 6
Param1 = 353 Param2 = 353 RealTimes = 7
Param1 = 391 Param2 = 391 RealTimes = 8
Param1 = 431 Param2 = 431 RealTimes = 9
程序执行非常不稳定,每次结构都不同,当然也不能用这些数据了。当把两个new int放到for循环中,执行结果是稳定的,但这样的代码晦涩难懂。在这里用PostMessage没有任何好处,所以建议使用SendMessage。
&&&&&&&分析想法2:
&&&&&&&1)&&已知一个线程处理了A,由于其他需要,此线程还需要处理B(必须在A完成之后)。需要新加入代码来实现,以前的代码为:
代码:code_3
DWORD&WINAPI&ThreadProc(LPVOID&lpParam)
&&&&&HWND&hWnd&= (HWND)lpP
&&&&&// Do some things
&&&&&::PostMessage(hWnd,&WM_MUST_DO_THING_A, 0, 0);
&&&&&return&0;
LRESULT&CMyDlg::OnMustDoThingA(WPARAM&wParam,&LPARAM&lParam)
&&&&&Do some things for A
&&&&&Do some things for B&&&//&费解,这是A的处理函数!!!
我们可以多加个消息,WM_MUST_DO_THING_B,然后用PostMessage发送,哦,不能这样,B一定要在A完成之后,现在唯一的处理方式只有对B的处理加入到A的消息处理函数中,这将导致费解的代码。如果在原来的线程函数中PostMessage为SendMessage,则不会如此。
&&&&如果A、B是不相关联的两个操作,为了以后扩展,也不该用PostMessage,这种情况下应该多创建一个线程进行处理。
2)&&对于需要处理的比较重要的操作(这些可能导致卡死):
LRESULT&CMyDlg::OnDoThing(WPARAM&wParam,&LPARAM&lParam)
&&&&Things To do. //&这里可能会卡死,但又必须处理
在这种情况下,建议使用SendMessageTimeout,当等待一段时间后,消息仍然没有处理完成,则程序放弃操作继续运行。
&&&&3)对于所有无关紧要的操作:
&&&&这些操作包括:清理磁盘临时文件等等,这些操作有没正常处理,程序并不关心,在这种情况下,则可使用PostMessage、
终上所述,我们得到如下结论:
1、&&PostMessage不能频繁的发送同一个消息,除非保证上次Post过的消息处理完成。
2、&&如果用SendMessage导致应用程序用户体验下降,应该检查消息处理函数,而不仅仅简单改为PostMessage。
3、&&如果消息是程序必须处理的,则不能使用PostMessage。
4、&&如果消息是程序必须处理,而又有可能导致程序卡死,则使用SendMessageTimeout。
5、&&如果消息是无关紧要的,则可以建议使用PostMessage。
6、&&对于WM_HOTKEY&等Windows特定的消息,则只能使用PostMessage(未在本文中说明)。
参考:http://blog.csdn.net/xt_xiaotian/article/details/2778689
Views(...) Comments()子线程中如何调用对话框的变量和函数 - CSDN博客
子线程中如何调用对话框的变量和函数
原文出处:
因为线程函数是全局的,而对话框的成员变量属于对话框类,所以不能调用,若想使用,一方面可以将对话框指针作为参数传递给线程,另一方面可以在子线程中向主线程发送消息,然后在消息响应函数里调用想使用的对话框的函数和变量。
传递指针参数的方法:在对话框的初始化函数中调用子线程,将对话框指针this传递给线程pOdometerQueryThread=AfxBeginThread(&OdometerQueryThreadProc,this,
THREAD_PRIORITY_NORMAL,0,0,NULL);
在子线程中,
UINT OdometerQueryThreadProc(LPVOID pParam)
CRobotcontrolDlg*
dlg=(CRobotcontrolDlg*)pP
while(m_bActive_SensorThread)
m_drive.drive_distance_query(&(dlg-&m_comm1_Drive));
网上好多资料说传递指针会很不安全,所谓“不安全”是因为两个线程访问同一个对象可能会有冲突,其实不只是对话框指针,凡是多个线程共用同一个东东都有这种可能,自己要知道哪些操作可能会发生冲突,并设法避免。
这个是 MFC 的一个雷区
=================================================
MfC各对象和win32 handles之间的映射关系记录在线程局部存储之中,因此,你没有办法把&&&
一个MFC对象从某线程手上交到另一个线程手上,你也不能够在线程之间传递MFC对象指针&&&
。。。。。。你不能够放一个指针到结构中,而该结构被一个worker线程使用。你不能够把&&&
一个指向CDialog或CView的指针交给另一个线程。当你需要调用view或document中的一个成&&&
员函数,特别象UpdateAllView这样的函数时,上述的限制很快会恶化。&&&
-----摘自《win32多线程程序设计》p294&&&
==================================================
比较安全的做法是发送消息。
可以自定义一个消息,在线程函数中利用SendMessage or PostMessage函数给主窗口发送消息,然后在窗口类的实现文件中定义消息处理函数即可,主要有以下步骤:
在对话框类的实现文件中:
1.定义消息
#define WM_MYMESSAGE WM_USER+100
2.在BEGIN_MESSAGE_MAP宏中增加一个入口将消息和函数关联起来
BEGIN_MESSAGE_MAP(CLmsTestDlg, CDialog)
//{{AFX_MSG_MAP(CLmsTestDlg)
..............................
ON_MESSAGE(WM_MYMESSAGE,OnMyMessage)&
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
3.定义消息处理函数
LRESULT CLmsTestDlg::OnMyMessage(WPARAM wParam,LPARAM lParam)
在对话框类的头文件中声明消息函数:
afx_msg LRESULT OnMyMessage(WPARAM wParam,LPARAM lParam);
这样的话就可以了,解决了线程函数中不能使用成员变量的问
本文已收录于以下专栏:
相关文章推荐
两个线程同时调用一个函数会出现什么情况?
最近在研究多线程,然后突然想到如果两个线程同时访问一个函数的话,要不要加锁呢,加锁怎么加,不加又怎样这样的问题..然后去网上找了些帖子学习学...
问题背景:在工作中遇到过一个问题,就是在两个线程同时调用同一个函数的时候,到底是应该在这个函数的内部什么处理上加上互斥。原因又是什么?
为了调查这个问题,我决定从以下三方面调查
1.线程中函数的调...
比如说,在ListBox里我添加了一个CString类型的成员变量m_str,我想用m_str.GetCount或m_str.GetText之类的方法,但这些在线程中就不能用了。 使用控件的成员变量和...
最近在使用 VC 开发软件时需要用到多线程同步来解决开发过程中遇到的问题。本来以为只要象控制台程序一样,在主线程创建子线程,并设置好相应的对象事件就能解决问题,但是等到真正做起来,才在实践中发现原来事...
多线程编程与传统的单线程编程有着很大的区别,尤其是在协调多个线程之间的工作流向的时候,需要考虑变量之间的共享、函数的传递、处理结果的返回,消息的传递等等,偶然在空间中看到了下面这篇博文,写的很精练,应...
子线程或其他类中是调用主对话框控件的GetDlgItem(IDC_XXX)功能是非常不安全的,但是同时又想要在子线程或其他类中调用此函数来设置主对话框中某个控件的内容,该怎么处理呢?
根据MVC...
方法一,在子线程中通过获得主线程中对应对话框的指针,然后向对话框发送WM_CLOSE消息。代码如下
在主线程对话框添加两个按钮,一个用来显示非模态对话框,另一个按钮用来启动子线程,在子线程中调用主线程...
waitpid系统调用】       功能描述: 等待进程改变其状态。所有下面哪些调用都被用于等待子进程状态的改 变,获取状态已改变的子进程信息。状态改变可被认为是:1.子进程已终止。2.信号导致子进...
waitpid系统调用】       功能描述: 等待进程改变其状态。所有下面哪些调用都被用于等待子进程状态的改 变,获取状态已改变的子进程信息。状态改变可被认为是:1.子进程已终止。2.信号导致子进...
java在子线程与主线程传递数据(回调函数)
他的最新文章
讲师:吴岸城
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)安全检查中...
请打开浏览器的javascript,然后刷新浏览器
< 浏览器安全检查中...
还剩 5 秒&三、 程序代码//////////////////////////////////////////////////////////////////////////////////////// sequence.cpp : Defines the entry point for the console application./*主要用到的WINAPI线程控制函数,有关详细说明请查看MSDN;线程建立函数:HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, // 安全属性结构指针,可为NULL;DWORD dwStackSize, // 线程栈大小,若为0表示使用默认值;&LPTHREAD_START_ROUTINE lpStartAddress, // 指向线程函数的指针;LPVOID lpParameter, // 传递给线程函数的参数,可以保存一个指针值;&DWORD dwCreationFlags, // 线程建立是的初始标记,运行或挂起;&LPDWORD lpThreadId // 指向接收线程号的DWORD变量;&);对临界资源控制的多线程控制的信号函数:HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, // 安全属性结构指针,可为NULL;BOOL bManualReset, // 手动清除信号标记,TRUE在WaitForSingleObject后必须手动//调用RetEvent清除信号。若为 FALSE则在WaitForSingleObject//后,系统自动清除事件信号;BOOL bInitialState, // 初始状态,TRUE有信号,FALSE无信号;LPCTSTR lpName // 信号量的名称,字符数不可多于MAX_PATH;//如果遇到同名的其他信号量函数就会失败,如果遇//到同类信号同名也要注意变化;);HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes, // 安全属性结构指针,可为NULLBOOL bInitialOwner, // 当前建立互斥量是否占有该互斥量TRUE表示占有,//这样其他线程就不能获得此互斥量也就无法进入由//该互斥量控制的临界区。FALSE表示不占有该互斥量&LPCTSTR lpName // 信号量的名称,字符数不可多于MAX_PATH如果//遇到同名的其他信号量函数就会失败,//如果遇到同类信号同名也要注意变化;);//初始化临界区信号,使用前必须先初始化VOID InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection // 临界区变量指针);//阻塞函数//如果等待的信号量不可用,那么线程就会挂起,直到信号可用//线程才会被唤醒,该函数会自动修改信号,如Event,线程被唤醒之后//Event信号会变得无信号,Mutex、Semaphore等也会变。DWORD WaitForSingleObject(HANDLE hHandle, // 等待对象的句柄DWORD dwMilliseconds // 等待毫秒数,INFINITE表示无限等待);//如果要等待多个信号可以使用WaitForMutipleObject函数*/#include "stdafx.h"#include "stdlib.h"#include "memory.h"HANDLE evtT //事件信号,标记是否所有子线程都执行完/*下面使用了三种控制方法,你可以注释其中两种,使用其中一种。注意修改时要连带修改临界区PrintResult里的相应控制语句*/HANDLE evtP //事件信号,标记事件是否已发生//CRITICAL_SECTION csP //临界区//HANDLE mtxP //互斥信号,如有信号表明已经有线程进入临界区并拥有此信号static long ThreadCompleted = 0;&/* 用来标记四个子线程中已完成线程的个数,当一个子线程完成时就对ThreadCompleted进行加一操作, 要使用InterlockedIncrement(long* lpAddend)和InterlockedDecrement(long* lpAddend)进行加减操作*///下面的结构是用于传送排序的数据给各个排序子线程struct MySafeArray{long*int iL};//打印每一个线程的排序结果void PrintResult(long* Array, int iLength, const char* HeadStr = "sort");//排序函数unsigned long __stdcall BubbleSort(void* theArray); //冒泡排序unsigned long __stdcall SelectSort(void* theArray); //选择排序unsigned long __stdcall HeapSort(void* theArray); //堆排序unsigned long __stdcall InsertSort(void* theArray); //插入排序/*以上四个函数的声明必须适合作为一个线程函数的必要条件才可以使用CreateThread建立一个线程。(1)调用方法必须是__stdcall,即函数参数压栈顺序由右到左,而且由函数本身负责栈的恢复, C和C++默认是__cdecl, 所以要显式声明是__stdcall(2)返回值必须是unsigned long(3)参数必须是一个32位值,如一个指针值或long类型(4) 如果函数是类成员函数,必须声明为static函数,在CreateThread时函数指针有特殊的写法。如下(函数是类CThreadTest的成员函数中):static unsigned long _stdcall MyThreadFun(void* pParam);handleRet = CreateThread(NULL, 0, &CThreadTestDlg::MyThreadFun, NULL, 0, &ThreadID);之所以要声明为static是由于,该函数必须要独立于对象实例来使用,即使没有声明实例也可以使用。*/int QuickSort(long* Array, int iLow, int iHigh); //快速排序int main(int argc, char* argv[]){long data[] = {123,34,546,754,34,74,3,56};int iDataLen = 8;//为了对各个子线程分别对原始数据进行排序和保存排序结果//分别分配内存对data数组的数据进行复制long *data1, *data2, *data3, *data4, *data5;MySafeArray StructData1, StructData2, StructData3, StructData4;data1 = new long[iDataLen];memcpy(data1, data, iDataLen && 2); //把data中的数据复制到data1中//内存复制 memcpy(目标内存指针, 源内存指针, 复制字节数), 因为long的长度//为4字节,所以复制的字节数为iDataLen && 2, 即等于iDataLen*4StructData1.data = data1;StructData1.iLength = iDataLdata2 = new long[iDataLen];memcpy(data2, data, iDataLen && 2);StructData2.data = data2;StructData2.iLength = iDataLdata3 = new long[iDataLen];memcpy(data3, data, iDataLen && 2);StructData3.data = data3;StructData3.iLength = iDataLdata4 = new long[iDataLen];memcpy(data4, data, iDataLen && 2);StructData4.data = data4;StructData4.iLength = iDataLdata5 = new long[iDataLen];memcpy(data5, data, iDataLen && 2);unsigned long TID1, TID2, TID3, TID4;&//对信号量进行初始化evtTerminate = CreateEvent(NULL, FALSE, FALSE, "Terminate");evtPrint = CreateEvent(NULL, FALSE, TRUE, "PrintResult");//分别建立各个子线程CreateThread(NULL, 0, &BubbleSort, &StructData1, NULL, &TID1);CreateThread(NULL, 0, &SelectSort, &StructData2, NULL, &TID2);CreateThread(NULL, 0, &HeapSort, &StructData3, NULL, &TID3);CreateThread(NULL, 0, &InsertSort, &StructData4, NULL, &TID4);//在主线程中执行行快速排序,其他排序在子线程中执行&QuickSort(data5, 0, iDataLen - 1);PrintResult(data5, iDataLen, "Quick Sort");WaitForSingleObject(evtTerminate, INFINITE); //等待所有的子线程结束//所有的子线程结束后,主线程才可以结束delete[] data1;delete[] data2;delete[] data3;delete[] data4;CloseHandle(evtPrint);return 0;}/*冒泡排序思想(升序,降序同理,后面的算法一样都是升序):从头到尾对数据进行两两比较进行交换,小的放前大的放后。这样一次下来,最大的元素就会被交换的最后,然后下一次循环就不用对最后一个元素进行比较交换了,所以呢每一次比较交换的次数都比上一次循环的次数少一,这样N次之后数据就变得升序排列了*/unsigned long __stdcall BubbleSort(void* theArray){long* Array = ((MySafeArray*)theArray)-&int iLength = ((MySafeArray*)theArray)-&iLint i, j=0;for (i = iLength-1; i &0; i--){for(j = 0; j & j++){if(Array[j] &Array[j+1]) //前比后大,交换{swap = Array[j];Array[j] = Array[j+1];Array[j+1] =}}}PrintResult(Array, iLength, "Bubble Sort"); //向控制台打印排序结果InterlockedIncrement(&ThreadCompleted); //返回前使线程完成数标记加1if(ThreadCompleted == 4) SetEvent(evtTerminate); //检查是否其他线程都已执行完//若都执行完则设置程序结束信号量return 0;}/* 选择排序思想:每一次都从无序的数据中找出最小的元素,然后和前面已经有序的元素序列的后一个元素进行交换,这样整个源序列就会分成两部分,前面一部分是 已经排好序的有序序列,后面一部分是无序的,用于选出最小的元素。循环N次之后,前面的有序序列加长到跟源序列一样长,后面的无序部分长度变为0,排序就 完成了。*/unsigned long __stdcall SelectSort(void* theArray){long* Array = ((MySafeArray*)theArray)-&int iLength = ((MySafeArray*)theArray)-&iLlong lMin, lSint i, j, iMinPfor(i=0; i & iLength-1; i++){lMin = Array[i];iMinPos =for(j=i + 1; j &= iLength-1; j++) //从无序的元素中找出最小的元素{if(Array[j] & lMin){iMinPos =lMin = Array[j];}}//把选出的元素交换拼接到有序序列的最后lSwap = Array[i];Array[i] = Array[iMinPos];Array[iMinPos] = lS}PrintResult(Array, iLength, "Select Sort"); //向控制台打印排序结果InterlockedIncrement(&ThreadCompleted); //返回前使线程完成数标记加1if(ThreadCompleted == 4) SetEvent(evtTerminate);//检查是否其他线程都已执行完//若都执行完则设置程序结束信号量return 0;}/* 堆排序思想:堆:数据元素从1到N排列成一棵二叉树,而且这棵树的每一个子树的根都是该树中的元素的最小或最大的元素这样如果一个无序数据集合是一个堆那 么,根元素就是最小或最大的元素堆排序就是不断对剩下的数据建堆,把最小或最大的元素析透出来。下面的算法,就是从最后一个元素开始,依据一个节点比父节 点数值大的原则对所有元素进行调整,这样调整一次就形成一个堆,第一个元素就是最小的元素。然后再对剩下的无序数据再进行建堆,注意这时后面的无序数据元 素的序数都要改变,如第一次建堆后,第二个元素就会变成堆的第一个元素。*/unsigned long __stdcall HeapSort(void* theArray){long* Array = ((MySafeArray*)theArray)-&int iLength = ((MySafeArray*)theArray)-&iLint i, j,for(i=0; i四、 小结对复杂的应用程序来说,线程的应用给应用程序提供了高效、快速、安全的数据处理能力。本实例讲述了线程处理中经常遇到的问题,希望对读者朋友有一定的帮助,起到抛砖引玉的作用。
阅读(...) 评论()

我要回帖

更多关于 mfc postmessage用法 的文章

 

随机推荐