MFC线程及实例

VC++ 专栏收录该内容
36 篇文章 0 订阅

转自:https://www.cnblogs.com/wenluderen/p/4246608.html

在MFC里面实现线程的实例
线程是一种从软件到硬件的技术,主要目的是为了提高运行速度,和多任务。

×××××需要储备的资料(他人的)×××××××××××××××××http://haobinnan.blog.51cto.com/775253/658446

多线程概述:


进程和线程都是操作系统的概念。
进程是在基于内存的概念,线程基于CPU的概念。CPU不清楚什么玩意叫进程,CPU处理的任务叫线程。


一个进程可以划分成多个线程给CPU处理。一个程序可以有多个进程 用于处理不同的事情。
进程是应用程序的执行实例,每个进程是由私有的虚拟地址空间、代码、数据和其它各种系统资源组成,进程在运行过程中创建的资源随着进程的终止而被销毁,所使用的系统资源在进程终止时被释放或关闭。
线程是进程内部的一个执行单元,系统创建好进程后,实际上就启动执行了该进程的主执行线程,主执行线程以函数地址形式,比如说main或WinMain函数,将程序的启动点提供给Windows系统。主执行线程终止了,进程也就随之终止。
每一个进程至少有一个主执行线程,它无需由用户去主动创建,是由系统自动创建的。
用户根据需要在应用程序中创建其它线程,多个线程并发地运行于同一个进程中。
一个进程中的所有线程都在该进程的虚拟地址空间中,共同使用这些虚拟地址空间、全局变量和系统资源,所以线程间的通讯非常方便,多线程技术的应用也较为广泛。


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处理。

 

工作线程创建过程:

工作者线程的AfxBeginThread的原型如下:

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

环境是VS2010  MFC  Win7  64位系统。

public:
    //工作线程创建第一步:在某个头文件里面声明一个函数。
    static UINT Scada_Operational(LPVOID pParam);
    int aaa;
};

extern CTestApp theApp;

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

//工作线程创建第二步:在对应的实现文件里面,定义这个函数。
UINT CTestApp::Scada_Operational(LPVOID pParam)
{
    Sleep(1000);
    AfxMessageBox(_T("准备赋值"));
    CTestApp* theApp = (CTestApp*)pParam;
    int bb=0;

    bb= theApp->aaa;
    Sleep(1000);
    AfxMessageBox(_T("完成赋值"));

    return 0;
}

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

//工作线程创建第三步:使用MFC特有的函数AfxBeginThread 将函数变为线程。
    AfxBeginThread(Scada_Operational,this);



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

户界面线程创建过程:

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

用户界面线程的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下有用。
);

 一个用户界面线程创建的实例::配套源代码:http://pan.baidu.com/s/1jGzLTye

0、建立一个基于MFC的对话框应用程序。
1、向程序中添加一个以CWinThread为基类的新类CUIThread,该类用于启动一个用户界面线程。

切换至“类视图”界面,右击项目名,添加类,基类选择CWinThread.

添加成功如下:

 //UIThread.h

#pragma once

// CUIThread

class CUIThread : public CWinThread
{
	DECLARE_DYNCREATE(CUIThread)

protected:
	CUIThread();           // 动态创建所使用的受保护的构造函数
	virtual ~CUIThread();

public:
	virtual BOOL InitInstance();
	virtual int ExitInstance();

protected:
	DECLARE_MESSAGE_MAP()
};


2、向程序中添加一个对话框资源,并建立相应的对话框类CUIThreadDlg,这个对话框的基类是CDialogEx。该对话框将被作为用户界面线程的主窗口。


3、在 UIThread.h 中加入#include "UIThreadDlg.h";

4、在 UIThread.h 中实例化CUIThreadDlg对话框:

public:
    CUIThreadDlg m_dlg;
5、在UIThread.cpp中的CUIThread::InitInstance()中加入

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


6、CUIThread::InitInstance()中创建的CUIThreadDlg将与主窗口在独立的线程中运行,可以在CUIThreadDlg中加入各种执行耗时任务的代码而不会影响主窗口的运行。


7、在原始对话框上面添加一个按钮 并创建点击事件响应函数,

//用户线程第七步:给原始对话框添加线程的头文件

#include "UIThread.h"

8、在函数中添加线程创建

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


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

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

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

几个常用的配套函数:

//获取线程对象

CWinThread* AFXAPIAfxGetThread();

//获取当前消息

MSG* AFXAPIAfxGetCurrentMessage();

//结束线程执行

void AFXAPIAfxEndThread(UINTnExitCode,BOOLbDelete =TRUE);

//初始化线程

void AFXAPIAfxInitThread();

//终止线程执行

void AFXAPIAfxTermThread(HINSTANCEhInstTerm =NULL);

 

  • 2
    点赞
  • 0
    评论
  • 14
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值