VC中CWinThread类以及和createthread API的区别分析

本文实例讲述了VC中CWinThread类以及和createthread API的区别分析,分享给大家供大家参考。具体分析如下:

CWinThread

CObject
 └CCmdTarget
    └CWinThread

CWinThread对象代表在一个应用程序内运行的线程。运行的主线程通常由CWinApp的派生类提供;CWinApp由CWinThread派生。另外,CWinThread对象允许一给定的应用程序拥有多个线程。

CWinThread支持两种线程类型:工作者线程(Worker Thread)和用户界面线程(UI thread)。工作者线程没有收发消息的功能(没有消息队列):例如,在电子表格应用程序中进行后台计算的线程。

用户界面线程具有收发消息的功能,并处理从系统收到的消息。CWinApp及其派生类是用户界面线程的例子。其它用户界面线程也可由CWinThread直接派生。

CWinThread类的对象存在于线程的生存期。如果你希望改变这个特性,将m_bAutoDelete设为FALSE。

要使你的代码和MFC是完全线程安全的,CWinThread类是完全必要的。框架使用的用来维护与线程相关的信息的线程局部数据由CWinThread对象管理。由于依赖CWinThread来处理线程局部数据(Thread Local Storage),任何使用MFC的线程必须由MFC创建。例如,由运行时函数_beginthreadex创建的线程不能使用任何MFC API。

为了创建一个线程,调用AfxBeginThread函数。根据你需要工作者线程还是用户界面线程,有两种调用AfxBeginThread的格式。如果你需要用户界面线程,则将指向你的CWinThread派生类的CRuntimeClass的指针传递给AfxBeginThread。如果你需要创建工作者线程,则将指向控制函数的指针和控制函数的参数传递给AfxBeginThread。对于工作者线程和用户界面线程,你可以指定可选的参数来修改优先级,堆栈大小,创建标志和安全属性。

AfxBeginThread线程将返回指向新的CWinThread对象的指针。
与调用AfxBeginThread相反,你可以构造一个CWinThread派生类的对象,然后调用CreateThread。如果你需要在连续创建和终止线程的执行之间重复使用CWinThread对象,这种两步构造方法非常有用。

CWinThread类成员

数据成员

m_bAutoDelete                      指定线程结束时是否要销毁对象 
m_hThread                             当前线程的句柄 
m_nThreadID                         当前线程的ID 
m_pMainWnd                         保存指向应用程序的主窗口的指针 
m_pActiveWnd                       指向容器应用程序的主窗口,当一个OLE服务器被现场激活时

构造函数

CWinThread                           构造一个CWinThread对象 
CreateThread                          开始一个CWinThread对象的执行

操作

GetMainWnd                          查询指向线程主窗口的指针 
GetThreadPriority                    获取当前线程的优先级 
PostThreadMessage               向另外的CWinThread对象传递一条消息 
ResumeThread                       减少一个线程的挂起计数 
SetThreadPriority                   设置当前线程的优先级 
SuspendThread                     增加一个线程的挂起计数

可重载函数

ExitInstance                         重载以进行线程终止时的清理工作 
InitInstance                           重载以实现线程实例的初始化 
OnIdle                                   重载以进行线程特定的空闲操作 
PreTranslateMessage           在消息被发送到Windows函数TranslateMessage和DispatchMessage之前过滤消息 
IsIdleMessage                      检测特定的消息 
ProcessWndProcException    截获线程消息和命令处理函数出现的所有未处理的异常 
ProcessMessageFilter           在特定的消息到达应用程序之前截获消息 
Run                                       线程的具有消息收发功能的控制函数,可重载以定制缺省的消息循环

AfxBeginThread和CreateThread具体区别

具体说来,CreateThread这个 函数是windows提供给用户的 API函数,是SDK的标准形式.
AfxBeginThread,是编译器对原来的CreateThread函数的封装,用与MFC.
而_beginthread是C的运行库函数。               
在使用AfxBeginThread时,线程函数的定义为:UINT  _yourThreadFun(LPVOID   pParam)
在使用CreateThread时,线程的函数定义为:  DWORD  WINAPI  _yourThreadFun(LPVOID pParameter)。

两个的实质都是一样的,不过AfxBeginThread返回一个CWinThread的指针,就是说他会new一个CWinThread对象,而且这个对象是自动删除的(在线程运行结束时),给我们带来的不便就是无法获得它的状态,因为随时都有可能这个指针指向的是一个已经无效的内存区域,所以使用时(如果需要了解它的运行状况的话)首先CREATE_SUSPENDED让他挂起,然后m_bAutoDelete=FALSE,接着才ResumeThread,最后不要了delete那个指针。

CreatThread就方便多了,它返回的是一个句柄,如果你不使用CloseHandle的话就可以通过他安全的了解线程状态,最后不要的时候CloseHandle,Windows才会释放资源(线程内核对象).
下面我们就来看一下AfxBeginThread函数的内部实现:

代码如下:

//启动worker线程
CWinThread* AFXAPI AfxBeginThread(AFX_THREADPROC pfnThreadProc, LPVOID pParam,
    int nPriority, UINT nStackSize, DWORD dwCreateFlags,
    LPSECURITY_ATTRIBUTES lpSecurityAttrs)
{

ASSERT(pfnThreadProc != NULL);

CWinThread* pThread = DEBUG_NEW CWinThread(pfnThreadProc, pParam);
         ASSERT_VALID(pThread);

if (!pThread->CreateThread(dwCreateFlags|CREATE_SUSPENDED, nStackSize,
                  lpSecurityAttrs))
         {
                  pThread->Delete();
                  return NULL;
         }
         VERIFY(pThread->SetThreadPriority(nPriority));
         if (!(dwCreateFlags & CREATE_SUSPENDED))
                  VERIFY(pThread->ResumeThread() != (DWORD)-1);
         return pThread;
}

//启动UI线程
CWinThread* AFXAPI AfxBeginThread(CRuntimeClass* pThreadClass,int nPriority, UINT nStackSize, DWORD dwCreateFlags, LPSECURITY_ATTRIBUTES lpSecurityAttrs)
{

ASSERT(pThreadClass != NULL);
        ASSERT(pThreadClass->IsDerivedFrom(RUNTIME_CLASS(CWinThread)));
        CWinThread* pThread = (CWinThread*)pThreadClass->CreateObject();
        if (pThread == NULL)
                AfxThrowMemoryException();
        ASSERT_VALID(pThread);
        pThread->m_pThreadParams = NULL;
        if (!pThread->CreateThread(dwCreateFlags|CREATE_SUSPENDED, nStackSize,
                lpSecurityAttrs))
        {
                pThread->Delete();
                return NULL;
        }
        VERIFY(pThread->SetThreadPriority(nPriority));
        if (!(dwCreateFlags & CREATE_SUSPENDED))
                VERIFY(pThread->ResumeThread() != (DWORD)-1);
        return pThread;
}

主要创建函数是

代码如下:

pThread->CreateThread(dwCreateFlags|CREATE_SUSPENDED, nStackSize,lpSecurityAttrs))

也就是

代码如下:

CWinThread::CreateThread

希望本文所述对大家的VC程序设计有所帮助。

(0)

相关推荐

  • windows2003 IIS6 部署MVC3和MVC4程序的方法

    1.服务器上安装SP2 和 IIS6 2.安装.Net Framework3.5 SP1(完整安装包,包含2.0 2.0SP1,237MB那个安装包http://www.jb51.net/softs/75472.html) 3.安装.Net Framework4.0 http://www.jb51.net/softs/25944.html 4.安装WindowsServer2003-KB968930-x86-CHS.exe,PowerShell 2.0的补丁(下载地址:http://www.mi

  • VC程序在Win32环境下动态链接库(DLL)编程原理

    本文详细讲述了VC程序在Win32环境下动态链接库(DLL)编程原理.分享给大家供大家参考.具体分析如下: 一般比较大的应用程序都由很多模块组成,这些模块分别完成相对独立的功能,它们彼此协作来完成整个软件系统的工作.其中可能存在一些模块的功能较为通用,在构造其它软件系统时仍会被使用.在构造软件系统时,如果将所有模块的源代码都静态编译到整个应用程序EXE文件中,会产生一些问题:一个缺点是增加了应用程序的大小,它会占用更多的磁盘空间,程序运行时也会消耗较大的内存空间,造成系统资源的浪费:另一个缺点是

  • Win10中VC2013安装Unit test组件出现问题解决方案

    话不多说,先上图~~~ 很多同学在Vs2013安装Unit test组件时会弹出这样的对话框,极其极其让人崩溃. 当我看到这个对话框时,首先中规中矩的去官网下载.NET(但是我怎么可能没有!游戏环境包都装了), 然后开始下载 才几百K,好easy,下载,运行,安装,oh!!!!!!!NO!!!!!! 好吧,又出问题了.去百度吧 按照百度的教程,找到了这个 . 我发现WIN10自带.NET,好吧并不是.NET的问题,咋办啊,搜索一圈发现并没有解答 决定自己解决 我觉得应该更新一下试试,毕竟2015

  • 终于明白了tc编译的dos程序和vc编译的win32控制台程序的区别

    它们有着本质的区别:1:一个是16的DOS程序,一个是标准的32的Windows应用程序.前者依然受着64KB内存分段约束,后者无忧无虑地使用着4GB内存地址空间.它们本来就是运行在不同的操作系统上的.别把他们混淆.DOS程序可以运行在windows上是因为有NTVDM.而你把VC生成的控制台程序放到DOS下只会得到!?This program cannot be run in DOS mode.2:如果你是用标准库编写的话,代码应该没多大差异的.但执行时调用库方式却差天共地.前者通过API模拟

  • VC WinExec打开指定程序或者文件的方法

    ⑴ 函数原型: UINT Win Exec(LPCSTR lpCmdLine, UINT uCmdShow); ⑵ 参数: lpCmdLine:指向一个空结束的字符串,串中包含将要执行的应用程序的命令行(文件名加上可选参数). uCmdShow:定义Windows应用程序的窗口如何显示,并为CreateProcess函数提供STARTUPINFO参数的wShowWindow成员的值. ⑶ 返回值: 若函数调用成功,则返回值大于31.若函数调用失败,则返回值为下列之一: ① 0:系统内存或资源已耗

  • win2008 IIS7无后缀URL部署问题 MVC4 MVC URL映射

    前言和中间一段都是我找到问题的过程和思维方法.没兴趣的可以直接跳过看后面的问题和解决. 前言: 问题发生在站点完成后,部署到服务器上.以为这个是最轻松的工作.结果悲剧了.windows server 2008 R2 上用的是IIS7,无法识别没有后缀的URL重定向.网上狂找.很多人会说这个问题很常见啊网上的资料很多啊.其实不然.今天我要给出大家这个问题的最官方的解决办法. 扯淡结束.先说问题.我搜索了很多以后发现几个问题. 第一,提供的解决方案都是老的.很多网站就是互相复制.配图大多都没有了.

  • VC6.0代码自动提示 VC6.0在win7环境下代码提示智能化

    作为程序猿的你,是否已经喜欢或习惯依赖IDE开发环境呢.作为Java程序猿,我还是蛮深深的依赖Java IDE开发环境滴,比如Eclipse或MyEclipse. 有了IDE环境,即使你想不起方法全名,只要知道某个前缀,或哪怕在提示列表中,一一查询,也可以找到自己想找的方法或属性.但是,若是IDE不这么智能,那你是否还能胜任吗? 目前小弟就遇到此情况.VC6.0环境,o(︶︿︶)o 唉,还是不能跟Eclispe相媲美的,也许是对VC6.0不熟悉,对Eclispe相对于熟悉,所以VC6.0使用起来

  • VC中CWinThread类以及和createthread API的区别分析

    本文实例讲述了VC中CWinThread类以及和createthread API的区别分析,分享给大家供大家参考.具体分析如下: CWinThread CObject  └CCmdTarget     └CWinThread CWinThread对象代表在一个应用程序内运行的线程.运行的主线程通常由CWinApp的派生类提供:CWinApp由CWinThread派生.另外,CWinThread对象允许一给定的应用程序拥有多个线程. CWinThread支持两种线程类型:工作者线程(Worker

  • VC++中图像处理类CBitmap的用法

    VC++中图像处理类CBitmap的用法 class CBitmap : public CGdiObject { DECLARE_DYNAMIC(CBitmap) public: static CBitmap* PASCAL FromHandle(HBITMAP hBitmap); // Constructors CBitmap(); BOOL LoadBitmap(LPCTSTR lpszResourceName); BOOL LoadBitmap(UINT nIDResource); BOO

  • VC中删除类的两种操作方法

    本文实例讲述了VC中删除类的两种操作方法.分享给大家供大家参考.具体方法如下: 方法一: 应该是先在windows里面删除.h和.cpp文件,然后打开项目,Ctrl-W打开Class    wizard,选这个Dialog类,然后提示找不到了,选remove,然后到File    view列表里面选这两个文件,按Delete删除,这样才彻底,否则.clw文件内会保留信息的 方法二: 在你的工程的FileView中删除相应的h文件和cpp文件,然后把工程关了 到相应文件夹下,把该类的h和cpp文件

  • ES6 javascript中class类的get与set用法实例分析

    本文实例讲述了ES6 javascript中class类的get与set用法.分享给大家供大家参考,具体如下: 与 ES5 一样, 在 Class 内部可以使用get和set关键字, 对某个属性设置存值函数和取值函数, 拦截该属性的存取行为. class MyClass { constructor() { // ... } get prop() { return 'getter'; } set prop(value) { console.log('setter: ' + value); } }

  • Android中的Dalvik和ART详解及区别分析

    要想知道Dalvik和ART区别分析,首先我们要分别知道这两者是什么? 什么是Dalvik? Dalvik是Google公司自己设计用于Android平台的虚拟机. Dalvik虚拟机是Google等厂商合作开发的Android移动设备平台的核心组成部分之一. 它可以支持已转换为 .dex格式的Java应用程序的运行,.dex格式是专为Dalvik设计的一种压缩格式,适合内存和处理器速度有限的系统. Dalvik 经过优化,允许在有限的内存中同时运行多个虚拟机的实例,并且每一个Dalvik 应用

  • C++中sprintf使用的方法与printf的区别分析

    本文实例讲述了C++中sprintf使用的方法与printf的区别.分享给大家供大家参考.具体分析如下: 首先我们在MSDN看一下printf的原型和sprintf的原型 复制代码 代码如下: int printf( const char *format [, argument]... ); 和 复制代码 代码如下: int sprintf( char *buffer, const char *format [, argument] ... ); 从定义来看两者的功能其实很相似的. 如果你接触的

  • java中重载、覆盖和隐藏三者的区别分析

    重载:方法名相同,但参数不同的多个同名函数 注意:1.参数不同的意思是参数类型.参数个数.参数顺序至少有一个不同 2.返回值和异常以及访问修饰符,不能作为重载的条件(因为对于匿名调用,会出现歧义,eg:void a ()和int a() ,如果调用a(),出现歧义) 3.main方法也是可以被重载的 覆盖:子类重写父类的方法,要求方法名和参数类型完全一样(参数不能是子类),返回值和异常比父类小或者相同(即为父类的子类),访问修饰符比父类大或者相同 两同两小一大  注意:子类实例方法不能覆盖父类的

  • C#中new的用法及与override的区别分析

    C#中new的用法有三种: (1)new是运算符,用于创建对象和调用构造函数.如Class1=new Class1();也可以为值类型调用默认的构造函数如int a=new int();此时a=0. (2)new是修饰符,用于隐藏基类成员的继承成员.override不能隐藏积累成员的继承成员.如: using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace A {

  • PHP中break及continue两个流程控制指令区别分析

    以下举例说明break 用来跳出目前执行的循环,并不再继续执行循环了. 复制代码 代码如下: <?php $i = 0; while ($i < 7) { if ($arr[$i] == "stop") { break; } $i++; } ?> continue 立即停止目前执行循环,并回到循环的条件判断处,继续下一个循环. 复制代码 代码如下: <?php while (list($key,$value) = each($arr)) { if ($key =

  • jQuery中的.bind()、.live()和.delegate()之间区别分析

    DOM树 首先,可视化一个HMTL文档的DOM树是很有帮助的.一个简单的HTML页面看起来就像是这个样子: 事件冒泡(又称事件传播) 当我们点击一个链接时,其触发了链接元素的单击事件,该事件则引发任何我们已绑定到该元素的单击事件上的函数的执行. 复制代码 代码如下: $('a').bind('click',function(){alert('that tickles!')}) 因此一个单击操作会触发alert函数的执行. click事件接着会向树的根方向传播,广播到父元素,然后接着是每个祖先元素

随机推荐