zoukankan      html  css  js  c++  java
  • 30、深入浅出MFC学习笔记,多线程

    一、基本概念

    1、模块:一段可执行的程序(包括EXEDLL),其程序代码、数据、资源被加载到内存中,由系统建置一个数据结构来管理它,就是一个模块。这里所说的数据结构,名为Module DatabaseMDB),其实就是PE格式中的PE表头,可以从WINNT.H 档中找到一个IMAGE_NT_HEADER 结构,就是它。

    2、进程:就是一大堆拥有权(ownership)的集合。进程拥有地址空间(由memory context决定)、动态配置而来的内存、文件、执行线程、一系列的模块。操作系统使用一个所谓的Process DatabasePDB)数据结构,来记录(管理)它所拥有的一切。

    3、线程:系统以一个特定的数据结构(Thread DatabaseTDB)记录执行线程的所有相关资料,包括执行线程局部储存空间(Thread Local StorageTLS)、消

    息队列、handle表格、地址空间(Memory Context )等。

    进程主要表达「拥有权」的观念,执行线程则主要表达模块中的程序代码的「执行事实」。

    4CPU调度单位是执行线程。调度器据以排序的,是每个执行线程的优先权。

    5、一般,timeslice20milliseconds

    6PDB连接模块示例

    wps_clip_image-28024

    7、当Windows 加载器将程序加载内存中,KERNEL32挖出一些内存,构造出一个PDB、一个TDB、一个以上的MDBs(视此程序使用到多少DLL而定)。针对TDB,操作系统又要产生出memory context(就是在操作系统书籍中提到的那些所谓page tables)、消息队列、handle表格、环境数据结(EDB)。当这些系统内部数据结构都构造完毕,指令指位器(Instruction Pointer)移到程序的进入点,才开始程序的执行。

    8、会被冻结,表示这个执行线程「要去抓取消息,而执行线程所附带的消息队列中却没有消息」。

        冻结有两种方法:一种是SuspendThread,另外一种是暂时冻结Sleep

    9、线程上下文:狭义来讲是指一组缓存器值(包括指令指位器IP)。

    10Worker ThreadsUI Threads

        从Windows 操作系统的角度来看,执行线程并未分类。但从MFC的角度看,则把执行线程划分为和使用者接口无关的worker threads,以及和使用者接口

    UI)有关的UI threads

        基本上,当我们以::CreateThread 产生一个执行线程,并指定一个执行线程函数,它就是一个worker thread,除非在它的生命中接触到了输入消息-这时候它应该有一个消息循环,以抓取消息,于是该执行线程摇身一变而为UI thread

    注意,执行线程本来就带有消息队列。而如果执行线程程序代码中带有一个消息循环,就称为UI thread

    11、用多线程的时机

    把所有UIUser Interface)动作都集中在主执行线程中,其它的「纯种运算工作」考虑交给worker threads

    12、创建多线程

    应该先产生一个CWinThread对象,再调用其成员函数CreateThread或全域函数AfxBeginThread将执行线程产生出来。因为CWinThread::CreateThread AfxBeginThread不只是::CreateThread 的一层包装,更做了一些application framework所需的内部数据初始化工作,并确保正确的C runtime library版本。

    1)建立Worker Threads

        利用函数CreateThread或全域函数AfxBeginThread去做。

    示例程序

    CWinThread* pThread = AfxBeginThread(ThreadFunc, &Param);
    ...
    UINT ThreadFunc (LPVOID pParam)
    {
    ...
    }
    

    2)建立UI Threads

    产生CWinThread 对象,为了借助其中的消息循环,CWinThread::Run

    示例程序

    class CMyThread : public CWinThread
    {
    DECLARE_DYNCREATE(CMyThread)
    public:
    void BOOL InitInstance();
    };
    IMPLEMENT_DYNCREATE(CMyThread, CWinThread)
    BOOL CMyThread::InitInstance()
    {
    ...
    }
    CWinThread *pThread = AfxBeginThread(RUNTIME_CLASS(CMyThread));
    

    3)线程的结束

        对于worker thread,执行线程函数return,执行线程也就结束了。或者执行线程函数也可以调用AfxEndThread,结束一个执行线程。

        UI执行线程因为有消息循环的关系,必须在消息队列中放一个WM_QUIT,才能结束执行线程。放置的方式和一般Win32程序一样,调用::PostQuitMessage 即可办到。亦或者,在执行线程的任何一个函数中调用AfxEndThread,也可以结束执行线程。

        不论worker thread UI thread,都需要一个CWinThread 对象,当执行线程结束,记得把该对象释放掉(利用delete)。

    参考

    [1] 深入浅出MFC

  • 相关阅读:
    接口和抽象类的区别
    MFC之ListCtrl动态添加按钮
    C++类间转换之dynamic_cast
    字符串提取
    C++实现快速排序
    MFC中CListCtrl类依靠CImageList贴图并显示不同图像
    北工大耿丹学院16级计科院3班C语言课程助教学期总结
    C语言课程2——我们交流的工具:Coding.net
    salt-minion安装脚本
    zabbix邮件报警脚本
  • 原文地址:https://www.cnblogs.com/mydomain/p/1968092.html
Copyright © 2011-2022 走看看