博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
进程与线程
阅读量:5856 次
发布时间:2019-06-19

本文共 3782 字,大约阅读时间需要 12 分钟。

我们可以把进程看作是一个正在独立运行的独立的程序,在内存中有其完备的数据空间和代码空间。

线程是在某一个进程中单独运行的单元,也就是说,线程存在于进程之中。一个进程有多个或者单个线程组成,各个线程共享相同的代码和全局数据,但是各有其自己的堆栈。由于每一个线程有一个堆栈,所以局部变量对每一个线程来说是私有的。由于所有的线程共享相同的代码和全局数据,它们比进程更紧密,比单独的进程间更趋向于相互作用。

 

一个进程与线程的最重要的区别是:线程拥有自己的全局数据。线程存在于进程中,因此一个进程的全局变量有所有的线程共享。

 

 

我们编写一个程序,来说明一下,为什么使用多线程!

新建一个基于对话框的应用程序,在主对话框IDD_SINGLETHEAD_DIALOD中添加一个Button按钮,设置属性,使它的响应函数为延迟5秒,代码如下:

void CSingThreadDlg::OnFiveSecondDelag( ){    Sleep(5000);}

发现整个对话框处于死机的状态,就是因为单线程状态下,程序只能等待。这时候有必要采用多线程的方法。

一。怎样创建线程

创建多线程的函数有很多:(1)全局函数AfxBeginThread( ... );

                                   (2)  CreatThread( ... );

                                  (3)_beginthread( )和_beginthreadex()函数

 

我们详细讲解第一个函数:

MSDN上给出如下定义:

CWinThread* AfxBeginThread(   AFX_THREADPROC pfnThreadProc,   LPVOID pParam,   int nPriority = THREAD_PRIORITY_NORMAL,   UINT nStackSize = 0,   DWORD dwCreateFlags = 0,   LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL );CWinThread* AfxBeginThread(   CRuntimeClass* pThreadClass,   int nPriority = THREAD_PRIORITY_NORMAL,   UINT nStackSize = 0,   DWORD dwCreateFlags = 0,   LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL );

各个参数的说明如下:

返回值: 一个指向新线程的线程对象

pfnThreadProc : 线程的入口函数,声明一定要如下: UINT MyThreadFunction( LPVOID pParam );
pParam : 传递入线程的参数,注意它的类型为:LPVOID,所以我们可以传递一个结构体入线程.
nPriority : 线程的优先级,一般设置为 0 .让它和主线程具有共同的优先级.
nStackSize : 指定新创建的线程的栈的大小.如果为 0,新创建的线程具有和主线程一样的大小的栈
dwCreateFlags : 指定创建线程以后,线程有怎么样的标志.可以指定两个值:

          CREATE_SUSPENDED : 线程创建以后,会处于挂起状态,直到调用: ResumeThread

          0 : 创建线程后就开始运行.
lpSecurityAttrs : 指向一个 SECURITY_ATTRIBUTES 的结构体,用它来标志新创建线程的安全性.如果为 NULL ,那么新创建的线程就具有和主线程一样的安全性.

 

之所以有两个函数,是因为线程分为两种:用户界面线程、工作者线程(我们将在下一节中介绍)

 

二.怎样终止一个线程

终止线程的方法有三种:

(1)可以在自身内部调用AfxEndThread()来终止自身的运行;

(2)可以在线程的外部调用Terminate()来强行终止一个线程的运行,然后调用closehandle()来释放线程所占用的堆栈。Terminate()有资源泄漏,因此要慎用这个函数。

(3)设置一个全局变量,改变这个全局变量,通知线程的执行函数返回,则该线程终止。这种方式通过线程执行函数的返回来终止线程,是一种安全的方式。

 

三.编写线程函数

需要注意的是:线程函数必须为一个独立的函数,因而,线程函数通常为全局函数或者静态成员函数。如果该线程函数一定要定义为一个类的成员函数,那么一般要把这个函数声明为静态的。

 

下面我们用一个实例来说明线程和进程的概念:我们写一个简单的伪代码:

(1)首先建立一个基于单文档类的MFC程序,不要忘记要支持Winsock类。

(2)在菜单中添加一个菜单项,并分别添加三个子菜单:启动线程、结束线程、启动进程。

(3)为启动线程添加消息消息相应函数:

 

VOID Cview::OnStartThread( ){    // TODO: Add your command handler code here        flag = false;    //flag 为标志位,用于结束线程。类似于第三种结束线程的方式。    if(numThread<2)  //numThread为允许开启的线程的数目,在这里,我们允许的数目为2个    {        numThread++;        AfxBeginThread(AddPicture,this);//AddPicture 为线程函数    } }

 

(3)添加全局的线程函数(如前所述,必须为全局或者静态成员函数,这里我们用全局的函数)

1 UINT AddPicture(LPVOID p) 2 { 3     if (TRUE ==flag) 4     {     5         switch(numThread) 6         { 7         case 1: 8             {             9                 AfxMessageBox("线程1启动");//执行功能110                 break;11             }12         case 2:13             {14                 AfxMessageBox("线程2启动");;//执行功能215                 break;16             }17         default:18             AfxEndThread(0);//结束进程19             //return 0;20         }21         22         23     }24     else 25         AfxEndThread(0);26     return 0;27 28 }

(4)为“结束线程”添加消息消息相应函数

void ampleView::IsStop(){	flag = FALSE;	numThread = 0;	}

  

这样,我们就基本完成了多线程的基本功能,当你点击“运行线程”的菜单项时,就会在客户区出现“线程1运行”的对话框;当你再次点击时,会出现

“线程2运行”的对话框;当你点击“结束线程”时,就会终止整个线程的运行。

 

--------------------------------------------------------------------------------------------------------------------------------------------

下面我们再在上面程序的基础上,打开一个进程,用于加深进程和线程的理解:

 

再建立一个菜单项,名称为--开启进程

添加代码如下:

void Cview::OnCreatePress(){    TCHAR currentPath[MAX_PATH];    GetModuleFileName(NULL,currentPath,MAX_PATH);    PROCESS_INFORMATION pi;//进程信息    STARTUPINFO si = {
sizeof(si} }; BOOL ret = CreateProcess(NULL,currentPath,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi); if(ret) { //父进程与子进程之间不需要信息的交换,因此可以关闭子进程的主线程句柄和子程序句柄 CloseHandle(pi.hThread); //关闭子进程语句 CloseHandle(pi.hProcess); } }

完成!当我们点击开启线程后,就会跳出一个和原界面相同的进程界面。

 

 

 

 

 

转载于:https://www.cnblogs.com/CBDoctor/archive/2012/05/25/2518396.html

你可能感兴趣的文章
java错误分析_Java常见错误分析(一)
查看>>
java 错误提示 行数不变_Java树集容器()给出错误的结果
查看>>
python httpstr find_Python string.rfind方法代碼示例
查看>>
java不是百分之百面向对象_java方法传值还是传引用的问题
查看>>
php语言源码安装教程,源码包安装php-Go语言中文社区
查看>>
php分享到微博,Wordpress怎么将选中内容分享到新浪微博
查看>>
php占市场份额,PHP 目前的市场占用率(Market Share)
查看>>
怎么写php扩展插件,php如何写插件
查看>>
wp-cron.php do=,WordPress使用WP-Cron函数定时执行任务
查看>>
php的常用标签有哪些,html标签元素有哪些种类?html的常用标签元素的介绍
查看>>
Ios php格式视频,IOS音频和视频(Audio & Video)
查看>>
php怎么设置input大小,js实现input输入框点击变大缩小
查看>>
java swing请求页面接口,java swing 远程调用接口
查看>>
java中file系统找不到指定的路径,java.io.FileNotFoundException:.\cfg\users(系统找不到指定的路径)...
查看>>
matlab如何清屏的运行,Matlab(1) -- Matlab清屏命令
查看>>
java集成kafka依赖包怎么导入,Kafka指南-源码导入Idea
查看>>
matlab 规律,01用PYTHON下载数据,而后用MATLAB编程探讨规律
查看>>
php 发布拼多多,拼多多补贴换增长的故事还能讲多久?
查看>>
matlab实现zca去白化,白化算法
查看>>
vs环境c++语言教学视频,基于VS Code的C++语言的构建调试环境搭建指南
查看>>