在进行多线程程序设计的时候,我们经常用到AfxBeginThread函数来启动一条线程
该函数使用起来非常的简单方便,其定义如下

CWinThread* AfxBeginThread(
   AFX_THREADPROC pfnThreadProc,//线程函数地址
   LPVOID pParam,//线程参数
   int nPriority = THREAD_PRIORITY_NORMAL,//线程优先级
   UINT nStackSize = 0,//线程堆栈大小,默认为1M
   DWORD dwCreateFlags = 0,//
   LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL 
);

CWinThread* AfxBeginThread(
   CRuntimeClass* pThreadClass,
   int nPriority = THREAD_PRIORITY_NORMAL,
   UINT nStackSize = 0,
   DWORD dwCreateFlags = 0,
   LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL 
);

参数说明:
pfnThreadProc:线程函数的地址,该参数不能设置为NULL,线程函数必须定义成全局函数或者类的静态成员函数
例如:
UINT myThreadFunc(LPVOID lparam)
或者
class A
{
public:
        static UINT __stdcall myThreadFunc(LPVOID lparam);
}
之所以要定义成类的静态成员函数,是因为类的静态成员函数不属于某个类对象,这样在调用函数
的时候就不用传递一个额外的this指针.

pThreadClass:指向从CWinThread派生的子类对象的RUNTIME_CLASS

pParam:要传递给线程函数的参数

nPriority:要启动的线程的优先级,默认优先级为THREAD_PRIORITY_NORMAL(普通优先级),关于线程
 优先级的详细说明请参考Platform SDK SetThreadPriority函数说明

nStackSize:新线程的堆栈大小,如果设置为0,则使用默认大小,在应用程序中一般情况下线程的默认堆栈大小
 为1M

dwCreateFlags:线程创建标志,该参数可以指定为下列标志
 CREATE_SUSPENDED:以挂起方式启动线程,如果你在线程启动之前想初始化一些CWinThread类中的一些成员变量
 比如:m_bAutoDelete或者你的派生类中的成员变量,当初始化完成之后,你可以使用CWinThread类的ResumeThread
 成员函数来恢复线程的运行
 如果把该标志设置为0,则表示立即启动线程
lpSecurityAttrs:指向安全描述符的指针,如果使用默认的安全级别只要讲该参数设置为NULL就可以了!

上面就是AfxBeginThread函数的简单说明,我们在使用的时候一般情况下只要指定前两个参数,其他
参数使用默认值就可以.嗯,的确,使用起来是很简单,只要这个函数一被调用,就创建了一个线程.
但是大家有没有想过,AfxBeginThread函数究竟是如何启动的线程呢?它的内部是如何实现的呢?

下面我们就来看一下AfxBeginThread函数的内部实现

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

return NULL;
#else
         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;
#endif //!_MT)
}

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

return NULL;
#else
        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;
#endif //!_MT
}

从上面的代码中可以看出AfxBeginThread所做的事情主要有以下几点:

1.在heap中配置一个新的CWinThread对象(worker线程)
代码如:CWinThread* pThread = DEBUG_NEW CWinThread(pfnThreadProc, pParam);
调用CRuntimeClass结构中的CreateObject函数创建CWinThread对象
CWinThread* pThread = (CWinThread*)pThreadClass->CreateObject();
CRuntimeClass以及MFC相关类的内部实现,详情请参考
《深入浅出MFC》侯捷著

2.调用CWinThread::CreateThread()并设定属性,使线程以挂起状态产生
pThread->CreateThread(dwCreateFlags|CREATE_SUSPENDED, nStackSize,lpSecurityAttrs);

3.设定线程的优先权
pThread->SetThreadPriority(nPriority);

4.调用CWinThread::ResumeThread
pThread->ResumeThread();

通过上面的说明,我想大家对该函数到底在内部都做了什么,应该有一个初步的了解了!
对于VC老手来说,这篇文章可能并没有什么可读之处,但是对于初学者来说,还是有一定的
价值的!
总之,希望这篇文章能给各位一点点的帮助!

mfc afxbeginthread()的更多相关文章

  1. (转)MFC中获得各个类的指针/句柄 ID的总结

    http://www.cnblogs.com/ylhome/archive/2009/10/06/1578478.html 一般我们使用的框架是VC提供的Wizard生成的MFC App Wizard ...

  2. MFC通过对话框窗口句柄获得对话框对象指针

       C***Dialog* pWnd= (C***Dialog*)FromHandle(hWnd); //由句柄得到对话框的对象指针    pWnd->xxx( );              ...

  3. MFC 获得各类指针、句柄的方法(转)

    原文转自 https://blog.csdn.net/abcjennifer/article/details/7480019 1.MFC中获取常见类句柄<视图类,文档类,框架类,应用程序类> ...

  4. MFC获取各类指针句柄

    最近有些人在问MFC编程一些要点,有一些句柄的获取.指针的获取是常见的问题,本文将对这些问题做以解释,参考了前人的笔录(见reference),希望能够帮助大家更方便地进行MFC程序开发. 一般我们使 ...

  5. 使用MFC中的AfxBeginThread创建多线程

    创建一个基于对话框的工程,工程名为CreateThreadRect   在CreateThreadRect.cpp中增加一个ThreadProc函数,代码如下   工作者线程的函数必须是全局函数或静态 ...

  6. 用MFC库函数AfxBeginThread()来创建线程

    在进行多线程程序设计的时候,我们经常用到AfxBeginThread函数来启动一条线程该函数使用起来非常的简单方便,其定义如下: 1.函数原型 CWinThread* AfxBeginThread( ...

  7. MFC的多线程操作

    记得用MFC做了一个图像自动修复软件,当时没有多线程操作这一概念,由于图像修复算法比较复杂,因此,当执行图像修复时,程序就像卡死了似得而不能做其他操作.其实MFC对这种情况有一种很好地解决方案,那就是 ...

  8. MFC 框架技术简单研讨

    引用:http://www.cnblogs.com/chinazhangjie/archive/2011/09/20/2181986.html 正文: 第一讲 Win32 App  和  MFC Fr ...

  9. VC++ AfxBeginThread 与 CreateThread 的区别

    简言之:AfxBeginThread是MFC的全局函数,是对CreateThread的封装.    CreateThread是Win32 API函数,前者最终要调到后者.具体说来,CreateThre ...

随机推荐

  1. requestAnimationFrame实现一帧的函数节流

    用一个变量判断raf的回调是否已经执行了,已经执行了说明过了一帧,通常是16.7ms,达到了函数节流一帧的目的. var locked = false; window.addEventListense ...

  2. vue的nextTick的实现

    vue的nextTick是用浏览器支持的方法模拟nodejs的process.nextTick 老版本的vue用如下方法来模拟 Promise.thenMutationObserver(Mutatio ...

  3. AnnotationConfigApplicationContext.的用法的核心代码

    public static void main(String[] args) {ApplicationContext ctx = new AnnotationConfigApplicationCont ...

  4. com.mongodb.MongoException$CursorNotFound: cursor not found on server异常处理

    java链接MongoDB处理大量数据时经常碰到cursor not found 的异常,其实是超时所致 Exception in thread "main" com.mongod ...

  5. ppk和pem证书互转

    首先你得去下载个putty pem:通用证书格式 ppk:为putty下面的专有格式     pem->ppk 直接通过putty下的puttygen.exe 选的Load private ke ...

  6. 问题总结——window平台下grunt\bower安装后无法运行的问题

    一.问题: 安装grunt或者bower后,在cmd控制台运行grunt -version 或者 bower -v会出现:“xxx不是内部或外部命令,也不是可运行的程序或批处理文件”,

  7. Sencha Touch MVC 中 store 的使用

    I have a UserStore that I want to load after succesful login of a user. I can't get this to work i.e ...

  8. linux下输出tomcat控制台信息

    进入tomcat/logs/目录执行命令:tail -f catalina.out即可

  9. vue this.$router.push 页面不刷新

    解决办法: 使用 watch,观察路由,发生变化重新获取数据 <script> export default { data() { return { data: {} } }, metho ...

  10. EL表达式中获取list长度(JSTL函数用法)

    在jsp页面中不能通过${list.size}取列表长度,而是 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" pref ...