(1)熟悉windows系统提供的线程创建与撤销系统调用。
(2)掌握windows系统环境下线程的创建与撤销方法。
(3)掌握CreateThread()函数和ExitThread()函数。
(1).实验在windows XP,VC++6.0环境下进行。在这一步,安装了Windows XP虚拟机,学会了创建一个控制台工程文件。
(2).百度句柄的含义:句柄(handle),有多种意义,第一种解释:句柄是一种特殊的智能指针 。当一个应用程序要引用其他系统(如数据库、操作系统)所管理的内存块或对象时,就要使用句柄。句柄是Windows用来标志应用程序中建立的或是适用的对象的唯一整数,Windows大量使用了句柄来标识对象。
(3).参照实验指导学习函数原型--CreateThread()函数:--线程创建
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES IpThreadAttributes,
DWORD dwStackSize,
LPTHREAD_START_ROUTINE IpStartAddress,
LPVOID IpParameter,
DWORD dwCreationFlags,
LPDWORD IpThreadId
);
!!!实例化:HANDLE h1 = CreateThread( NULL, 0, Fun1, NULL, 0, NULL );
<1>.参数IpThreadAttributes指定线程安全属性,当其为NULL时,则线程获取默认安全描述符。
<2>.参数dwStackSize指定线程堆栈的初始大小,以字节为单位。如果此参数为0,则新线程使用可执行文件的默认大小。
<3>.参数IpStartAddress指定由线程执行的自定义函数的指针。
<4>.参数IpParameter指定自定义函数的参数。
<5>.参数dwCreationFlags指定线程创建后所处的状态。该值为0,表示线程创建后立即执行。
<6>.参数IpThreadId指定接收线程标识符的变量的指针。该参数为 NULL,则不返回线程标识符。
---如果函数成功,则返回值是新线程的句柄。如果函数失败,则返回值为NULL。
(4).参照实验指导学习函数原型--ExitThread()函数:--撤销进程
<1>.ExitThread()用于撤销当前进程。
<2>.该函数没有返回值。
<3>.用法举例:ExitThread(0);//参数0表示要撤销进程中的所有线程
(5).参照实验指导学习函数原型--TerminateThread()函数:--终止线程
TerminateThread()用于终止当前线程。该函数与ExitThread()的区别在于,ExitThread()在撤销线程时将该线程所拥有的资源全部归还给系统,而TerminateThread()不归还资源。在实验中用ExitThread()函数居多。
(6).参照实验指导学习函数原型--Sleep()函数:--挂起线程
该函数没有返回值。
(7).参照实验指导学习函数原型--CloseHandle()函数:--关闭句柄
返回值:如果函数调用成功,则返回值为非0值;如果函数调用失败,则返回值为0.若要得到更多的错误信息,调用函数GetLastError()查询。
实验1.使用系统调用CreatThread()创建一个子线程,并在子线程中显示;Thread is Running!.为了能让用户清楚地看到线程的运行情况,使用Sleep()使线程挂起5s,之后使用ExitThread(0)撤销进程.
实验2.模仿教学视频中的程序,改写一个吃苹果进程,采用多线程‘吃苹果’与单一线程‘吃苹果’做对比。了解多线程的运行原理。
实验一:
#include "stdafx.h"
#include "01.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
void ThreadName1();
static HANDLE hHandle1=NULL;
DWORD dwThreadID1;
using namespace std;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
hHandle1 = CreateThread( (LPSECURITY_ATTRIBUTES) NULL,
0,
(LPTHREAD_START_ROUTINE) ThreadName1,
(LPVOID) NULL,
0, &dwThreadID1 );
Sleep(5000);
CloseHandle(hHandle1);
ExitThread(0);
return nRetCode;
}
void ThreadName1()
{
printf("Thread is running!");
}
实验二:
#include "stdafx.h"
#include "011.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
CWinApp theApp;
using namespace std;
void eatApple(int number){
Sleep((3 - number)*1000);
printf("I'm eatting #%d apples.\n",number);
}
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
HANDLE h1 = NULL;
HANDLE h2 = NULL;
HANDLE h3 = NULL;
DWORD Th1 = NULL;
DWORD Th2 = NULL;
DWORD Th3 = NULL;
int a=0;
int b=1;
int c=2;
h1 = CreateThread( (LPSECURITY_ATTRIBUTES) NULL,
0,
(LPTHREAD_START_ROUTINE) eatApple,
(LPVOID) a,
0, &Th1 );
h2 = CreateThread( (LPSECURITY_ATTRIBUTES) NULL,
0,
(LPTHREAD_START_ROUTINE) eatApple,
(LPVOID) b,
0, &Th2 );
h3 = CreateThread( (LPSECURITY_ATTRIBUTES) NULL,
0,
(LPTHREAD_START_ROUTINE) eatApple,
(LPVOID) c,
0, &Th3 );
eatApple(a);
eatApple(b);
eatApple(c);
ExitThread(0);
return nRetCode;
}
实验一总结:
在Windows系统中进程是资源的拥有者,线程是系统调用的基本单位。
进程创建后,其主线程也随即被创建。在该实验中,有创建了一个名为
ThreadName1的子线程,该子线程与主线程并并发的被系统调度。
为了能让用户清楚地看到线程的运行情况,在主线程创建了子线程之后,
将主线程挂起5s,以确保子线程能够运行完毕,
之后调用ExitThread(0)将所有线程撤销。
实验二总结:
在该实验中,创建了Th1 Th2 Th3三个子线程,为了能清楚地看到线程的运行情况,在主线程创建了子线程之后,
打印“I'm eatting apples”以确保能够直观的看出运行情况,
之后调用ExitThread(0)将所有线程撤销。
ExitThread(0)的使用:
void eatApple(int number){
Sleep((3 - number)*1000);
printf("I'm eatting #%d apples.\n",number);
while(1){
printf("#%d is exiting.\n\n",number);
ExitThread(0);
}
}
PS:视频中用的是这种方法,但是我在学习文档中看到ExitThread(0)表示要撤销进程中的所有线程。所以我没用视频中的方法,直接在代码后面加了“ExitThread(0);”语句。
文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib
文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang
文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些
文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器
文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距
文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器
文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn
文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios
文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql
文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...
文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120
文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数