1 / 73

第 2 章 进程与线程

第 2 章 进程与线程. 2.1 进程与线程的基本概念 2.2 进程管理( Process 类) 2.3 线程管理( Thread 类) 2.4 线程同步与线程池 2.5 BackgroundWorker 组件. 2.1 进程与线程的基本概念. 进程 正在执行的 程序 称为 进程 qq 程序 VS 正在运行的 qq 进程. 为什么要有进程?. 2.1 进程与线程的基本概念. 78. 130. 150. 228. 280. 300. 378. 430. 450. 时 间. 输入机. 处理器. 磁带机.

ceri
Download Presentation

第 2 章 进程与线程

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第2章 进程与线程 2.1 进程与线程的基本概念 2.2 进程管理(Process类) 2.3 线程管理(Thread类) 2.4 线程同步与线程池 2.5 BackgroundWorker组件

  2. 2.1 进程与线程的基本概念 进程 正在执行的程序称为进程 qq程序 VS 正在运行的qq进程 为什么要有进程?

  3. 2.1 进程与线程的基本概念 78 130 150 228 280 300 378 430 450 时 间 输入机 处理器 磁带机 处理器利用率:52/(78+52+20)≈35% 顺序程序设计的例子 while(1) { input,process,output } 1次执行 1次执行 1次执行

  4. 2.1 进程与线程的基本概念 程序的并发执行 I1 I2 I3 P1 P3 P2 O1 O2 O3 所谓程序的并发执行是指:若干个程序同时在系统中执行,这些程序的执行在时间上是重叠的,一个程序的执行尚未结束,另一个程序的执行已经开始。

  5. 2.1 进程与线程的基本概念 程序的并发执行 S1 S3 S4 S2 一个程序的多条语句的并发执行: S1: a:=x+2 S2: b:=y+5 S3: c:=a+b S4: d:=c+6

  6. 2.1 进程与线程的基本概念 进程 进程是资源调度和分配的基本单位 内存 设备 进程是一个可独立调度和分派的基本单位(早期) 与进程相关的信息包括: 进程标志、与进程关联的文件名 执行的程序和数据,运行时间、在存储器中的位置 占用的内存容量等。

  7. 2.1 进程与线程的基本概念 并发执行: 宏观上并行 微观上串行 例如: 查毒软件进程在下载更新病毒库(A)的同时要进行杀毒(B) A----B-----A----B A B交替占用CPU, 由于时间非常短,所以对用户来说宏观上感觉在下载和查毒同时进行。而实际执行为串行执行

  8. 2.1 进程与线程的基本概念 为什么要有线程?

  9. 2.1 进程与线程的基本概念 进程的两个基本属性 进程是一个资源分配的基本单位。 进程是一个可独立调度和分派的基本单位。 进程作为一个资源拥有者,在创建、撤消、切换中,系统必须为之付出较大时空开销。所以系统中进程的数量不宜过多,进程切换的频率不宜过高,但这也就限制了并发程度的进一步提高。

  10. 2.1 进程与线程的基本概念 线程的引入 将进程的上述两个属性分开 线程作为调度和分派的基本单位,不同时作为独立分配资源的单位;线程会被频繁调度和切换。 进程作为拥有资源的单位,不进行频繁切换。

  11. 2.1 进程与线程的基本概念 线程的引入 引入进程的目的是为了使多个程序更好的并发执行,改善资源利用率、提高系统效率。 引入线程则是为了减少并发执行时所付出的时空开销,使并发粒度更细、并发性更好。 线程的定义:是进程中的一个实体,是被系统独立调度的基本单位。

  12. 进程 进程1 … … … … … … … … … … … … 线程1 分配处理机 线程2 线程3 2.1 进程与线程的基本概念

  13. 2.1 进程与线程的基本概念 线程 将一个进程划分为若干个独立的执行流,每一个执行流均称为一个线程。 线程是CPU调度和分配的基本单位,异步执行。 线程共享进程的资源 线程分类 主线程:每个进程都有一个主线程。 辅助线程:除了主线程以外,还可以给一个进程分配若干个子线程,从而达到多个任务并发执行的目的。

  14. 2.1 进程与线程的基本概念 改程序 点击按钮后不断循环输出测试信息,程序失去响应? 利用辅助线程不断循环输出测试信息 离得开多线程么?

  15. 2.2 进程管理(Process类) 任务1:获取进程信息

  16. 2.2 进程管理(Process类) 1、Process类位于System.Diagnostics命名空间下。 2、对本机(本地计算机) (1)可以启动、终止某个进程 (2)可以查看进程相关信息,如CPU利用率等 (3)可以查看进程工作状态 3、对远程计算机 (1)可以查看远程计算机相关信息 (2)无法直接启动、终止远程计算机 4、在一个程序中处理其他的程序(例如调用其他.exe文件、.dll文件、快捷方式等),实际上就是对进程进行管理。

  17. 2.2.1 获取进程信息 写程序 – 检查qq进程是否启动 – 给出提示信息 检查一下计算机中QQ是否正在运行?

  18. 2.2.1 获取进程信息 1、如何获取进程信息 (1)获取本地计算机的所有进程: Process[] myProcesses = Process.GetProcesses(); (2)获取本地计算机上指定名称的进程: Process[] myProcesses = Process.GetProcessesByName("进程名称"); 注意:(a)进程名称不带扩展名。 (b)可以是任何一个可执行文件 例如: Process[] myProcesses = Process.GetProcessesByName (“WindowApplication1");

  19. 2.2.1 获取进程信息(续) (3)获取远程计算机的所有进程: Process[] myProcesses = Process.GetProcesses (remoteMachineName); 例如: Process[] myProcesses = Process.GetProcesses ("192.168.0.1"); (4)获取远程计算机上指定名称的进程: Process[] myProcesses = Process.GetProcessesByName( "远程进程名称",remoteMachineName);

  20. 程序举例【例2-1】 【例2-1】观察本机运行的所有进程,并显示进程相关的信息。要求: (1)用DataGridView显示所有进程信息 (2)鼠标单击DataGridView某处时,判断单击的是否为行开头或者某个单元格,如果是,显示该行进程的详细信息 (运行效果见下页图)

  21. 2.2.1 获取进程信息(续) 运行效果:

  22. 2.2.2 启动和停止进程 任务2描述: 项目类型:常用的数据库应用程序(上学期ADO.NET) 环境: 数据库:SQLServer2008 \Oracle 10g\ DB2 V9.5 开发语言: C# 需求: 部署实际项目时: 将数据库表、存储过程、从开发环境  生产环境? 如何初始化数据?

  23. 2.2.2 启动和停止进程 任务2方案: 方法1:实验室建立好,拷贝数据库文件? SqlServer 2008 可以 通用么?NO! 一般方法:执行sql脚本 让用户命令行执行?你会,别人可以么?软件需求! 学习目标:通过Process类在程序中调用sql脚本

  24. 2.2.2 启动和停止进程 任务3:停止、启动进程、远程主机进程管理

  25. 2.2.2 进程管理(Process类) 写程序 —启动记事本 –空白记事本 –指定文件名 让你的程序打开一个记事本文档吧! 试一下:Process类

  26. 2.2.2 进程管理(Process类)-- 重点 启动进程 (1)创建一个Process组件的实例,例如: Process myProcess = new Process(); (2)设置其对应的StartInfo属性,指定要运行的应用程序名以及传递的参数: myProcess.StartInfo.FileName = "文件名"; myProcess.StartInfo.Arguments = "参数"; (3)调用该实例的Start方法启动该进程。 myProcess.Start();

  27. 2.2.2 进程管理(Process类) 文件名:KwMusic.EXE 路径:C:\Program Files\KWMUSIC\KwMusic.EXE 改程序 :启动音乐盒 让你的程序启动音乐盒! 注意:路径!

  28. 2.2.2 进程管理(Process类) 一些细节 仅文件名提示找不到? 默认寻找路径:环境变量+ 当前目录 加路径信息。自己的,建议用相对路径! 指定图形用户界面的打开方式。例如: myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Normal; 细节记不住? 看提示! 定位问题 断点调试!必杀技!

  29. 2.2.2 进程管理(Process类) 改程序 -- 添加关闭部分处理 关闭本机所有记事本程序 是否提示保存信息? 还是强制关闭?

  30. 2.2.2 进程管理(Process类) 停止进程 --- 两种方法 CloseMainWindow + Close(释放资源): 有图形界面 Kill + WaitForExit(等待退出): 所有程序 如何选择?CloseMainWindow VS Kill 有图像界面?先礼后兵 先尝试 CloseMainWindow 后尝试 Kill 没有图形用户界面 Kill方法 注意:异常处理!

  31. 2.2.2 进程管理(Process类) 【例2-2】启动、停止和观察Notepad进程。 (StartStopProcess)要求: (1)用ListView显示“记事本”进程信息。 (2)用Process类方法启动进程。 (3)终止进程时,把所有“记事本”进程全部终止。

  32. 项目应用2:调用sql脚本 public void ExecuteSqlFile(string strFileName) { Process SqlProcess = new Process(); SqlProcess.StartInfo.FileName= "osql.exe"; SqlProcess.StartInfo.Arguments="-U sa-P sa123-d mydb-i"+ strFileName; SqlProcess.StartInfo.WindowStyle= ProcessWindowStyle.Hidden; ….. SqlProcess.Start(); SqlProcess.WaitForExit(); SqlProcess.Close(); } 略读补充示例:ProcessOsql 参考资料:osql说明文档

  33. 开发时间对比 JAVA VS C# C#开发速度 >> JAVA 为什么不用C#? 跨平台性对比 JAVA >> C# 考虑查看远程主机信息 启动关闭远程主机进程? 考虑,Process类提供么? NO! 变通: 客户端 服务端 进程之间的通信 项目应用3:远程主机进程管理 33

  34. 2.2 进程管理 -- 小结 -----------------------获取进程实例------------------- GetProcessById方法:通过进程Id创建新的Process组件,并将其与本地计算机上的进程资源关联。 GetProcessById最多只有一个Process实例。 GetProcesses方法:获取本机上所有进程 GetProcessesByName方法:获取本机上特定名称的进程 ----------------------进程ID及进程名------------------ Id属性:获取关联进程的唯一标识符 ProcessName属性:获取该进程的名称,不包括路径和扩展名

  35. 2.2 进程管理 -- 小结 -----------------------获取及设置优先级--------------- BasePriority属性: 获取进程优先级(只读) PriorityClass属性:设置或更改进程优先级 -------------------进程其他信息------------------- MachineName属性:获取关联进程正在其上运行的计算机的名称。 MainModule属性:获取关联进程的主模块 Modules属性:获取由关联进程加载的模块 TotalProcessorTime属性:获取进程的总的处理器时间 StartTime属性:获取关联进程启动的时间 WorkingSet64属性:为进程分配的物理内存量(字节数)

  36. 2.2 进程管理 -- 小结 --------------------进程启动---------------------- Start方法:启动进程资源并将其与Process组件关联 StartInfo属性:获取或设置要传递给启动进程的文件名以及启动参数 ---------------------进程终止---------------------- Kill方法:强制终止进程 Close方法:释放与此组件关联的所有资源 CloseMainWindow方法:关闭具有用户界面的进程。 HasExited属性:指示关联进程是否已终止 WaitForExit方法:设置等待关联进程退出的时间,并在该段时间结束前或该进程退出前,阻止当前线程执行。

  37. 2.3 线程管理(Thread类) 2.3.1 前台线程与后台线程 2.3.2 线程基本操作 2.3.3 Volatile关键字 2.3.4 在一个线程中操作另一个线程的控件

  38. 2.3 线程管理(Thread类) Thread类位于System.Threading命名空间下。 Thread类是用于创建和控制线程的,对线程的常用操作有:启动、终止、合并和休眠等。 Thread类提供的常用属性 IsAlive属性:获取一个值,该值指示当前线程的执行状态。如果此线程已启动并且尚未正常终止,则为true;否则为false IsBackground属性:获取或设置一个值,该值指示某个线程是否为后台线程。是后台线程或即将成为后台线程,则为true;否则为false Priority属性:获取或设置一个值,该值指示线程的调度优先级

  39. 2.3 线程管理(Thread类)(续) Thread类提供的常用方法 Start方法:启动线程 Join方法:将指定的线程合并到当前线程中,并阻止当前线程执行,直到指定的线程终止或经过了指定的时间为止 Sleep方法:将当前线程阻止指定的毫秒数,零(0)表示应挂起此线程以使其他等待线程能够执行 Abort方法:在调用此方法的线程上引发ThreadAbortException,以开始终止此线程的过程。调用此方法通常会终止线程

  40. 2.3.2 线程的基本操作 1.启动线程 启动线程前,首先要创建一个线程。 创建线程的一般形式为: Thread t1 = new Thread(方法名); 对于不止一个参数的情况,可以先将这些参数封装到一个类中,然后传递该类的实例,在线程中,再通过该实例访问相应的数据,从而达到启动线程时传递多个参数的目的。 创建线程实例后,就可以调用Start方法启动线程了。例如: t1.Start(); //不带参数 t2.Start(“My name”); //带参数 注意: 调用Start只是告诉系统启动该线程,但是系统并不一定会立即启动它。

  41. 2.3.2 线程的基本操作 2.终止线程 两种方法: 事先设置一个布尔字段,在其他线程中通过修改该布尔量的值作为传递给该线程是否需要终止的判断条件,而在该线程中循环判断该布尔值,以确定是否退出线程,这是结束线程比较好的方法,实际应用中一般使用这种方法。 调用Thread类的Abort方法,该方法的最终效果是强行终止线程。

  42. 2.3.2 线程的基本操作 3. 暂停线程 在多线程应用程序中,有时候并不希望某一个线程继续执行,而是希望该线程暂停一段时间,这样,CPU就会将其时间片中剩余的部分让给另一个线程。 调用Thread类的Sleep方法可以实现这个功能。例如: Thread.Sleep(1000); 这条语句的功能是让当前线程暂停1000毫秒。 注意 Sleep方法是静态方法,暂停的是该语句所在的线程,而不是其他线程。

  43. 2.3.2 线程的基本操作 4.合并线程 Join方法用于把指定的线程合并到当前线程中,从而使其变为一个单个的线程。 如果一个线程t1在执行的过程中需要等待另一个线程t2结束后才能继续执行,可以在t1的代码块中调用t2的join方法。例如: t2.Join(); 功能:t1在执行到t2.Join()语句后,就处于暂停状态,直到t2结束后才会继续执行。 为了避免t1一直等待,可以在调用t2的Join方法的时候指定一个暂停时间,例如:t2.Join(100);

  44. 2.3.1 前台线程与后台线程 一个线程要么是后台线程要么是前台线程。 后台线程与前台线程类似,区别是后台线程不会影响进程终止。属于某个进程的所有前台线程都终止后,公共语言运行库就会结束该进程,而且所有属于该进程的后台线程也都会立即停止,而不管后台工作是否完成。 利用Thread对象的IsBackground属性,可以设置或判断一个线程是后台线程还是前台线程。 通过将某个线程的IsBackground属性设置为true,使其变为后台线程。 默认情况下,属于托管线程池的线程(即其IsThreadPoolThread属性为true的线程)都是后台线程,通过创建并启动新的Thread对象而生成的线程都是前台线程。

  45. 2.3.3 Volatile关键字 volatile修饰符表示所声明的字段可以被多个并发执行的线程修改。如果某个字段声明包含volatile关键字,则该字段将不再被编译器优化。这样可以确保该字段在任何时间呈现的都是最新的值。 对于由多个线程访问的字段,而且该字段没有用lock语句对访问进行序列化,声明字段时应该使用volatile修饰符。 volatile修饰符只能包含在类或结构的字段声明中,不能将局部变量声明为volatile。 在布尔型字段的声明中,添加volatile修饰符的方法如下: public volatile bool shouldStop;

  46. 2.3.3 Volatile关键字 volatile修饰符可应用于以下类型: (1)引用类型。 (2)指针类型(在不安全的上下文中)。 (3)整型,如sbyte、byte、short、ushort、int、uint、char、float和bool。 (4)具有整数基类型的枚举类型。 (5)已知为引用类型的泛型类型参数。 (6)IntPtr和UIntPtr。

  47. 2.3.4 在一个线程中操作另一个线程的控件 默认情况下,在Windows应用程序中,.NET Framework不允许在一个线程中直接操作另一个线程中的控件,这是因为访问Windows窗体控件本质上不是线程安全的。 在应用程序中,如果创建某控件的线程之外的其他线程试图调用该控件,则系统会引发一个InvalidOperationException异常。 有两种办法可以解决这个问题: (1)使用委托(delegate)操作另一个线程中的控件 (2)用BackgroundWorker组件在后台执行线程

  48. 2.3.4 在一个线程中操作另一个线程的控件(续) 利用委托调用另一个线程控件: delegate void AppendStringDelegate(string str); private void AppendString(string str) { if(richTextBox1.InvokeRequired) { AppendStringDelegate d = AppendString; richTextBox1.Invoke(d, str); } else { richTextBox1.Text += str; } }

  49. 程序举例【例2-3】 【例2-3】在Class1类中声明两个方法Method1和Method2,其中Method1不停地输出字符“a”,Method2不停地输出字符“b”,在Form1中启动线程执行Method1和Method2,并在RichTextBox中显示线程输出的字符。

  50. 2.4 线程同步与线程池 2.4.1 线程的优先级 2.4.2 线程同步 2.4.3 lock语句 2.4.4 线程池

More Related