进程和线程

Posted on 2018-01-09 10:12  阳光绿荫的早晨  阅读(148)  评论(0编辑  收藏  举报

进程:程序开始运行时,它便是一个进程;进程包括运行中的程序和程序所使用到的内存和系统资源;一个进程至少有一个主线程。

线程:线程是程序中的一个执行流,每个线程都有自己的寄存器(栈指针、程序计数器等),但代码区是共享的。即不同的线程可以执行同样的函数。

多线程:是指程序中包含多个执行流;即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说,允许单个程序创建多个并行执行的线程来完成各自的任务。

多线程的好处:提高CPU的利用率。在多线程的程序中,一个线程必须等待的时候,CPU可以继续运行其他线程而不是等待,从而大大提高程序的效率。

多线程的不利之处:

  1. 线程也是程序,所有线程需要占用内容,线程越多占用内存越多。
  2. 多线程需要协调和管理,所以CPU需要花时间来跟踪线程。
  3. 线程之间对共享资源的访问会相互影响,必须解决竞用共享资源问题。
  4. 线程太多会导致控制太复杂,最终可能导致太多BUG。

通过 Thread 类的静态属性 CurrentThread 可以获取当前正在执行的线程。

不管创建了多少个这个类的实例,但是类的静态属性在内存中只有一个。

很容易理解 CurrentThread 为什么是静态的--虽然有多个线程同时存在,但是在某一个时刻,CPU 只能执行其中一个! 

所有与多线程机制应用相关的类都是放在System.Threading命名空间中。

Thread有几个至关重要的方法:

  • Start( ) -- 启用线程;该方法只是通知CPU此线程可以被执行,但具体执行时机则由CPU自行决定。
  • Sleep(int) -- 静态方法,暂停当前线程指定的毫秒数
  • Abort( ) -- 通常使用该方法终止一个线程
  • Suspent( ) -- 该方法并不终止未完成的线程,仅仅是挂起线程,后期还可以恢复
  • Resume( ) -- 恢复Suspent( )方法挂起线程的执行

当线程之间争夺CPU时,CPU按照线程的优先级给予服务。

在C#应用程序中,存在5个不同优先级,由高至低分别是

  • Highest
  • AboveNormal 
  • Normal
  • BelowNormal
  • Lowest

系统默认优先级是TheradPriority.Normal ;通过设定线程优先级,可以合理的安排相对重要的线程优先执行,例如用户的响应等等。

线程的调度算法非常复杂。记住,优先级高的线程并不一定先执行,但 CPU 会将更多的时间片分给优先级高的线程,因此,在相同任务量的前提下,高优先级线程将会较快的完成任务。

 

Winform 中多线程的应用


 

       在 Winform 程序总,一般称绘制窗体和响应用户的线程为主线程,或 UI 线程。单线程最显著的缺点是,当一个事件发生,程序进行一个耗时的运算动作时,UI 线程会出现假死现象,此时会无视对用户的响应。

       下面的代码会模拟一些不同的情况:

 1 void DoSomething()
 2 {
 3     for (int i = 0; i < 900000000; i++)
 4     {
 5  
 6     }
 7     MessageBox.Show("It's finished.");
 8 }
 9  
10 void ShowStr(object obj)
11 {
12     var list = obj as List<string>;
13     if (list != null)
14     {
15         foreach (var item in list)
16         {
17             MessageBox.Show(item.ToString());
18         }                
19     }
20     else
21         MessageBox.Show("null");
22 }
23  
24 // UI 单线程,运行时窗体会卡死一段时间
25 private void btnUI_Click(object sender, EventArgs e)
26 {
27     DoSomething();
28 }
29  
30 // 调用无參函数,此时窗体能响应用户
31 private void btnThreadA_Click(object sender, EventArgs e)
32 {
33     Thread thread = new Thread(DoSomething);
34     thread.Start();
35 }
36  
37 // 当所有前台线程都关闭时,后台线程将立即结束运行,无条件的关闭
38 // 而前台线程运行时,即使关闭 Form 主程序,该线程仍将继续运行,直到计算完毕
39 private void btnThreadB_Click(object sender, EventArgs e)
40 {
41     Thread thread = new Thread(DoSomething);
42     thread.IsBackground = true;
43     thread.Start();
44 }
45  
46 // 调用有参函数
47 private void btnThreadC_Click(object sender, EventArgs e)
48 {
49     Thread thread = new Thread(ShowStr);
50     thread.Start(new List<string> { "Jacky", "Skysoot", "Sam" });
51 }

 

Thread 类的 4 个构造函数基本分为 2 类,有参和无參。而 ParameterizedThreadStart 委托定义的方法原型的参数为 Object 类型,这提高了传参最大的灵活性。当然,在被调用的函数内部,需要依据一定的约定将 Object 对象进行转型处理。