进程线程——并行画圆画方

仅供学习参考,如有不足之处,请予补充指正。

一、知识点回顾

为了能使程序并发执行,并且可以对并发执行的程序加以描述和控制,引入了”进程“的概念。

1、PCB(进程控制块):OS配置的专门的数据结构,系统利用PCB来描述进程的基本活动和活动过程,进而控制和管理进程

2、创建进程——创建进程实体中的PCB;撤销进程——撤销进程的PCB

3、进程是程序的一次执行,是拥有资源的独立单位

4、引入进程的目的:使多个程序能够并发执行,以提高资源利用率和系统吞吐量

5、进程特征:动态性、并发性、独立性、异步性

6、进程的三种状态:就绪状态、执行状态、阻塞状态

7、三种基本状态转换:就绪——执行(进程调度)、执行——就绪(时间片完)、执行——阻塞(I/O请求)、阻塞——就绪(I/O完成)

8、进程同步机制遵循规则:空闲让进、忙则等待、有限等待、让权等待

9、信号量机制:信号量的值仅由pv操作改变,虽然使用方便但是同步操作使用不当会导致系统死锁。

10、管程:模块化、抽象数据类型、信息掩蔽

11、管程与进程不同之处:二者都定义了数据结构,但是进程定义的——私有数据结构PCB,管程定义的——公共数据结构,如消息队列等;二者存在对各自数据结构上的操作,但进程——顺序程序执行,而管程——进行同步和初始化操作;设置进程目的——实现系统的并发性,设置管程目的——解决共享资源的互斥使用问题;进程工作方式——主动,管程工作方式——被动;进程之间能并发执行,管程不能;进程具有动态性,管程——资源管理模块,供进程调用;

12、进程通信:进程之间的信息交换

13、进程通信类型:共享存储器系统、管道(pipe)通信系统、消息传递系统、客户机-服务器系统

14、消息传递实现方式:直接消息传递系统(发送原语)、信箱通信(间接通信,信箱通信原语)

15、引入线程的目的:减少程序再并发执行时的空间开销,使得OS具有更好的并发性

16、线程:独立调度和分派的基本单位

二、效果图展示

三、详解

使用框架:VS中的MFC

主要实现功能:画圆、画方、按钮并发

实现函数:

        UINT DrawRectgle(LPVOID lpParam);//画圆
        UINT DrawRectgle(LPVOID lpParam);//画方

具体实现:

UINT DrawCircle(LPVOID lpParam)
{
	CWinThreadDlg* pDlg = (CWinThreadDlg*)lpParam;
	CDC* pDC;
    //GetDC()为一个指定窗口的客户端区域或者整个屏幕从一个设备上下文(DC)中提取一个句柄
	pDC = pDlg->GetDC();

	CPoint CirclePoint(180, 180);//原点

	COLORREF crColour = RGB(0, 0, 255);//颜色

	int R0 = 150; //半径	 

	const double degree_half = 0.008726; //每半度 2×3.1415 / 720 

	int i = 0;
	for (i = 0; i < 720; i++)
	{
        //SetPixelV()在指定的设备场景中设置一个像素的RGB值
		pDC->SetPixelV(
			CirclePoint.x + R0 * sin(degree_half * i),
			CirclePoint.y + R0 * cos(degree_half * i),
			crColour);
		Sleep(10);

	}

	return 0;
}
UINT DrawRectgle(LPVOID lpParam)
{
	CWinThreadDlg* pDlg = (CWinThreadDlg*)lpParam;
	CDC* pDC;
	pDC = pDlg->GetDC();

	CPoint CirclePoint(180, 180);//原点

	COLORREF crColour = RGB(255, 0, 0);//颜色

	int R0 = 150; //半径	 

	const double degree_half = 0.008726; //每半度 2×3.1415 / 720 

	//换个位置画方
	CirclePoint.x = CirclePoint.x + 2 * R0 + 10;

	float factor = 1.65; //屏幕宽度长度不协调,需要调节!!!
	float Delta = 2 * R0 / 180 * factor;

	int ii = 0;

	//上边
	for (ii = 0; ii < 180; ii++)
	{
		pDC->SetPixelV(
			CirclePoint.x + R0 - Delta * ii,
			CirclePoint.y - R0,
			crColour);
		Sleep(10);
	}

	//左边
	for (ii = 0; ii < 180; ii++)
	{
		pDC->SetPixelV(
			CirclePoint.x - R0,
			CirclePoint.y - R0 + Delta * ii,
			crColour);
		Sleep(10);
	}

	//下边
	for (ii = 0; ii < 180; ii++)
	{
		pDC->SetPixelV(
			CirclePoint.x - R0 + Delta * ii,
			CirclePoint.y + R0,
			crColour);
		Sleep(10);
	}

	//右边
	for (ii = 0; ii < 180; ii++)
	{
		pDC->SetPixelV(
			CirclePoint.x + R0,
			CirclePoint.y + R0 - Delta * ii,
			crColour);
		Sleep(10);
	}

	return 0;

}

按钮并行画圆画方实现:

        MFC提供了两个重载版的AfxBeginThread,一个用于用户界面线程,另一个用于工作者线程,区别在于用户界面线程能处理消息响应,而工作者线程不能。

        用户线程原型:

        

CWinThread* AFXAPI AfxBeginThread
(
    CRuntimeClass* pThreadClass,//派生类
    int nPriority, //优先级
    UINT nStackSize, //堆栈大小
    DWORD dwCreateFlags,//创建标识
    LPSECURITY_ATTRIBUTES lpSecurityAttrs//安全属性,NT下有用
)

        举例:

        工作者线程原型:

        

CWinThread* AFXAPI AfxBeginThread
(
    //线程的入口函数,声明一定要如下: UINT MyThreadFunction( LPVOID pParam );
    AFX_THREADPROC pfnThreadProc, 
    LPVOID pParam,//传递入线程的参数,注意它的类型为:LPVOID,所以我们可以传递一个结构体
    int nPriority, //优先级
    UINT nStackSize, //堆栈大小
    DWORD dwCreateFlags,//创建标识
    LPSECURITY_ATTRIBUTES lpSecurityAttrs  //安全属性
)

        AfxBeginThread除前面两个参数外,后面几个都是默认参数,可以省略。

        在这里我们用的是工作者线程,第一个参数是线程入口函数,第二个参数把this传过去,线程函数可以使用和操作类的成员。

        线程函数是静态类函数成员

// 画圆和画方(线程方式)
//同时调用两个函数分别画圆和画方
void CWinThreadDlg::OnBUTTONThread()
{
	// 画圆的函数:DrawCircle
	pThread_Circle = AfxBeginThread(DrawCircle, this);

	// 画方的函数
	pThread_Rectgle = AfxBeginThread(DrawRectgle, this);
}

        终止线程进程:碰到 return 0; 就会调用释放函数结束线程,这是释放线程最推荐的方式。

        其余方式:

       ExitProcess、 ExitThread函数强迫线程终止运行,会导致OS清理该线程使用的所有操作系统资源,但是C/C++资源不会被销毁,要避免使用, 不要自己调用;   

       TerminateProcess、 TerminateThread函数是异步的,并不能保证线程终止,要避免使用;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值