• MFC线程


    MFC中有两类线程,分别称之为工作者线程和用户界面线程。二者的主要区别在于工作者线程没有消息循环,而用户界面线程有自己的消息队列和消息循环。

             在MFC中,一般用全局函数AfxBeginThread()来创建并初始化一个线程的运行,该函数有两种重载形式,(为啥叫重载形式呢?因为系统中已经有了这两个函数,在使用的使用给予不同的变量不就是重载的定义吗??是的)分别用于创建工作者线程和用户界面线程。两种重载函数原型和参数分别说明如下: 

    CreateThread是一个API,而AfxBeginThread是MFC中的一个函数。后者在内部调用了前者。

    ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××

          对于工作线程来说,启动一个线程,首先需要编写一个希望与应用程序的其余部分并行运行的函数如Fun1(),

    接着定义一个指向CwinThread对象的指针变量*pThread,(在MFC中可以用App)

    调用AfxBeginThread(Fun1,param,priority)函数,返回值付给pThread变量的同时一并启动该线程来执行上面的Fun1()函数,

    其中Fun1是线程要运行的函数的名字,也既是上面所说的控制函数的名字,param是准备传送给线程函数 Fun1的任意32位值,

    priority则是定义该线程的优先级别,它是预定义的常数。

    线程函数是回调函数,线程函数在类内必须是静态成员函数,或者是类外声明的全局函数。

    因为静态成员函数不能访问类的非静态成员函数,所以在线程函数中要定义一个类的指针指向this指针,就可以用类的指针来调用类的成员函数。

    数据传递使用this处理。

    HMI  WORK线程   

    CWinThread* AfxBeginThread(

                           AFX_THREADPROC pfnThreadProc,//指向工作者线程的执行函数的指针,线程函数原型必须声明如下: UINTExecutingFunction(LPVOID pParam);

                            LPVOID pParam,/**///传递给线程函数的一个32位参数,执行函数将用某种方式解释该值。它可以是数值,或是指向一个结构的指针,甚至可以被忽略;

                          nPriority=THREAD_PRIORITY_NORMAL,//线程的优先级。如果为0,则线程与其父线程具有相同的优先级;

                           UINTnStackSize=0,//线程为自己分配堆栈的大小,其单位为字节。如果nStackSize被设为0,则线程的堆栈被设置成与父线程堆栈相同大小;

                           DWORDdwCreateFlags=0,//如果为0,则线程在创建后立刻开始执行。如果为CREATE_SUSPEND,则线程在创建后立刻被挂起;

                          LPSECURITY_ATTRIBUTES lpSecurityAttrs=NULL//线程的安全属性指针,一般为NULL;

    );

    源代码:http://pan.baidu.com/s/1mgrAxVM


     UI线程

    创建一个用户界面线程,首先要从类CwinThread产生一个派生类,同时必须使用DECLARE_DYNCREATE和IMPLEMENT_DYNCREATE来声明和实现这个CwinThread派生类。
      第二步是根据需要重载该派生类的一些成员函数如:ExitInstance();InitInstance();OnIdle(); PreTranslateMessage()等函数,最后启动该用户界面线程,调用AfxBeginThread()函数的一个版   本:

    CWinThread*AfxBeginThread(

    CRuntimeClass* pThreadClass,//从CWinThread派生的RUNTIME_CLASS类;

                           intnPriority=THREAD_PRIORITY_NORMAL,//线程优先级,如果为0,则与创建该线程的线程相同;

                           UINT nStackSize=0,//线程的堆栈大小,如果为0,则与创建该线程的线程相同;

                           DWORD dwCreateFlags=0,//一个创建标识,如果是CREATE_SUSPENDED,

    则在悬挂状态创建线程,在线程创建后线程挂起,否则线程在创建后开始线程的执行。

                           LPSECURITY_ATTRIBUTESlpSecurityAttrs=NULL//线程的安全属性,NT下有用。

    );

     范例 :

     

    1、建立一个基于MFC的对话框应用程序。
    2、向程序中添加一个以CWinThread为基类的新类CUIThread,该类用于启动一个用户界面线程。
    3、向程序中添加一个对话框资源,并建立相应的对话框类CUIThreadDlg,这个对话框的基类是CDialogEx。

        该对话框将被作为用户界面线程的主窗口。
    4、在UIThread.h中加入#include "UIThreadDlg.h"和并在CUIThread::InitInstance()中加入

    public:  
        CUIThreadDlg m_dlg; 
    
    BOOL CUIThread::InitInstance()  
    {  
        // TODO: 在此执行任意逐线程初始化  
      
           
        //用户线程第六步:添加创建程序  
        m_pMainWnd = &m_dlg;  
        m_dlg.DoModal();  
     ;  
        return TRUE;  
    } 

    5、CUIThread::InitInstance()中创建的CUIThreadDlg将与主窗口在独立的线程中运行,可以在CUIThreadDlg中加入各种执行耗时任务的代码而不会影响主窗口的运行。
    6、在 原始对话框上面添加一个按钮 并创建点击事件响应函数,

    //用户线程第七步:添加线程的头文件#include "UIThread.h"。

    在函数中添加线程创建

    void CTestGszDlg::OnBnClickedButton1()  
    {  
        // TODO: 在此添加控件通知处理程序代码  
        //CWinThread* p = AfxBeginThread(RUNTIME_CLASS(CUIThread));  
        //用户线程第八步:正式创建线程  
         AfxBeginThread(RUNTIME_CLASS(CUIThread));  
    }  

    7:我们创建的线程在结束的时候 销毁我们新建的对话框

    int CUIThread::ExitInstance()
    {
        m_dlg.DestroyWindow();
        return CWinThread::ExitInstance();
    }

    配套源代码:http://pan.baidu.com/s/1jGzLTye


    几个常用的配套函数

    //获取线程对象

    CWinThread* AFXAPIAfxGetThread();

    //获取当前消息

    MSG* AFXAPIAfxGetCurrentMessage();

    //结束线程执行

    void AFXAPIAfxEndThread(UINTnExitCode,BOOLbDelete =TRUE);

    //初始化线程

    void AFXAPIAfxInitThread();

    //终止线程执行

    void AFXAPIAfxTermThread(HINSTANCEhInstTerm =NULL);

  • 相关阅读:
    java -jar 远程调试
    正则
    python2和3的区别
    javaw 运行jar 指定编码
    windows kill 结束指定端口进程
    linux 查看nginx 安装目录
    node-mysql中防止SQL注入
    实用资源库和工具,极大缩减开发时间
    浏览器地址栏运行JavaScript代码
    css垂直居中方案
  • 原文地址:https://www.cnblogs.com/smh2015/p/6370001.html
Copyright © 2020-2023  润新知