进程: 表示资源分配的基本单位,有事调度运行的基本单位。从编程的角度,也可以看成一块包含了某些资源的内存区域。
理解;只要是打开应用程序,就会创建进程。
线程: 是程序中独立的指令流。在vs编译器输入代码的时候,系统会分析代码,用下划线标注遗漏的分号和其他语法错误,这就是一个后台线程完成。
Word文档需要一个线程等待用户输入,另一个线程进行后台搜索,第三个线程将写入的数据存储在临时文件中。运行在服务器上的应用程序中等待客户请求的线 程成为侦听线程。
进程包含资源,如Window句柄,文件系统句柄或其他内核对象。每个进程都分配的虚拟内存。一个进程至少包含一个线程。
一个应用程序启动,一般会启动一个进程,然后进程启动多个线程。
多线程:(multithreading)是指从软件或者硬件上实现多个线程并发执行的技术。
在以下情况中可能要使用到多线程
1、程序需要同时执行两个或多个任务:
程序要等待某事件的发生,例如用户输入,文件操作,网络操作,搜索等。
后台程序
优先任务
线程使用的相关函数:
1)引入线程名空间
using System.Threading
2)创建代理
ThreadStart代理对象名 = new ThreadStart(方法名);
3)创建线程
Thread 线程对象名 = new Thread(代理对象名);
4)启动线程
线程对象名.Start();
Diagnostics命名空间Process
类别 | 名称 | 作用 | (返回值)数据类型 |
属性 | ProcessName | 获取进程名称 | string |
属性 | ID | 获取进程唯一标示符 | int |
属性 | Treads | 进程中的线程集合 | Thread[] |
属性 | MachineName | 获取运行进程的计算机名称 | string |
方法 | GetCurrentProcess | 获取当前进程 | Process |
静态方法 | GetProcesses | 获取计算机中运行的进程 | Process[] |
静态方法 | Start | 启动进程 | process |
方法 | Kill | 关闭进程 | void |
线程同步:使用线程的一个重要的方面就是同步访问多个线程访问的任何变量。所谓同步,:是指在莫一时刻只有一个线程可以访问变量。如果不能确保变量的访问是同步的,就会产生错误。
C#为访问变量提供了一个非常简单的方式,即是使用C#关键字lock,用法如下;
lock(x) { DoSomething(); }
同步注意问题:
不要滥用同步
死锁
竞态条件
在书店可能某种书籍只有一本,而两个售货员同时售了这本书,如果是两个线程,怎么办。(解答如下)
使用C#中的lock关键字,再次关键字范围类的代码都是线程安全的。lock关键字定义一个标记,线程进入锁定范围必须获得这个标记。当锁定的是一个实例级对象的私有方法时使用方法本身所在对象的引用就可以了。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 using System.Threading.Tasks; 7 8 namespace 线程同步 9 { 10 public class BookShop 11 { 12 public int num = 1; 13 public void Sale() 14 { 15 int tmp; 16 lock (this) 17 { 18 tmp = num; 19 if (tmp > 0) 20 { 21 Thread.Sleep(1000); 22 num = num - 1; 23 Console.WriteLine("售出一本。"); 24 }else 25 { 26 Console.WriteLine("书没有了"); 27 } 28 } 29 } 30 } 31 32 class Program 33 { 34 static void Main(string[] args) 35 { 36 BookShop bk = new BookShop(); 37 Thread t1 = new Thread(new ThreadStart(bk.Sale)); 38 Thread t2 = new Thread(new ThreadStart(bk.Sale)); 39 t1.Start(); 40 t2.Start(); 41 Console.ReadLine(); 42 } 43 } 44 }
线程异步
对于单CPU而言,在单位时间内(也称时间片),只能执行一个线程,即只能干一件事。当一个线程的时间片用完时,系统会将该线程挂起,下一个时间内在执行另一个线程,如此,cup以时间片为间隔多个线程之间交替执行运算(其实这里还与每个线程的优先级有关,级别高的会优先处理)。由于交替时间间隔很短,所以造成了各个线程都在“同时”
工作的假象:线程异步就是解决类似前面提到的执行耗时任务是界面控件不能使用的问题。如创建一个次线程去专门执行耗时的任务,而其他如界面控件响应这个的任务交给另一个线程执行(往往由主线程执行)。这样,两个线程之间通过线程调度器短时间(时间片)内的切换,就模拟出多个任务“同时”被执行的效果。
总结两句话:
1,线程异步是指一个线程去执行,它的下一个线程不必等待它执行完就开始执行。
2,线程同步就是指一个线程等待上一个线程执行完之后才开始执行当前的线程。
同步调用与异步调用
同步调用:
委托的lnvoke方法用来进行同步调用,同步调用也可以叫阻塞调用,它将阻塞当前线程,然后执行调用,调用完毕后再继续向下进行。
异步调用
异步调用不阻塞线程,而是把调用塞到线程池中,程序主线程或UI线程可以继续执行。委托的异步调用通过Beginlnvoke和Endlnvoke来实现。
异步回调
用回调函数,当调用结束时会自动调用回调函数,解决了为等待用结果,而让线程依旧被阻塞的局面。
注意:Beginlnvoke和Endlnvode必须成对调用。即使不需要返回值,当Endlnvoke还是必须调用,否则可能会造成内存泄露。
线程池:
创建线程池需要时间。如果有不同的小任务要完成就可以事先创建许多线程,在完成这些任务时发出请求。这个线程数最好在需要更多的线程时增加,在需要释放资源时减少。
不需要自己创建线程池,系统已经有一个ThreadPool类管理线程。这个类会在需要时增减池中的线程的线程数,直到达到最高线程数。池中的最大线程数是可配置的。在双核中,默认设置为1023个工作线程和1000个I/o线程。也可以指定在创建线程池时应用立即启动的最小线程数,以及线程池中可用的最大线程数。如果有更多做作业要处理,线程池中线程的个数也到了极限,最新的作业就要排队,且必须等待线程完成任务。