一、Thread 基礎
進程: 當一個程式開始運行時,它就是一個進程,進程包括運行中的程式和程式所使用到的記憶體和系統資源。而一個進程又是由多個線程所組成的。
線程: 線程是程式中的一個執行流,每個線程都有自己的專有寄存器(棧指標、程式計數器等),但代碼區是共用的,即不同的線程可以執行同樣的函數(方法)。
多線程: 多線程是指程式中包含多個執行流,即在一個程式中可以同時運行多個不同的線程來執行不同的任務,也就是說允許單個程式建立多個並存執行的線程來完成各自的任務。
二、 多線程
優點:可以提高CPU的利用率。在多線程程式中,一個線程必須等待的時候,CPU可以運行其它的線程而不是等待,這樣就大大提高了程式的效率。
缺點:線程也是程式,所以線程需要佔用記憶體,線程越多佔用記憶體也越多;
多線程需要協調和管理,所以需要CPU時間跟蹤線程;
線程之間對共用資源的訪問會相互影響,必須解決競用共用資源的問題;
線程太多會導致控制太複雜,最終可能造成很多Bug;
三、控制線程的類和方法
類:using System.Threading; Thread類
Thread類的方法:Start(): 啟動線程;
Sleep(int):靜態方法,暫停當前線程指定的毫秒數;
Abort(): 通常使用該方法來終止一個線程;
Suspend(): 該方法並不終止未完成的線程,它僅僅掛起線程,以後還可恢複;
Resume(): 恢複被Suspend()方法掛起的線程的執行。
Priority 枚舉設定線程的優先順序,由高到低 Highest,AboveNormal,Normal,BelowNormal,Lowest;系統預設為ThreadPriority.Normal
在執行個體化Thread的執行個體,需要提供一個委託,在執行個體化這個委託時所用到的參數是線程將來啟動的方法。在.NET中提供了兩種啟動線程的方式,一種是不帶參數的啟動方式,另一種是帶參數的啟動方式。
1. 不帶參數的啟動方式
在大型緩衝的時候我們會經常會用線程,當前程式去緩衝中提取資料,開啟另一個線程判斷當前的快取資料是否到期,是否需要從資料庫提取最新資料。
定義性別的枚舉
/// <summary>
/// 姓名枚舉
/// </summary>
enum PersonSexTypeEnum
{
Man,
Woman,
}
定義Person 類,成員
internal class Person
{
/// <summary>
/// 姓名
/// </summary>
public string Name { get; set; }
/// <summary>
/// 年齡
/// </summary>
public int Age { get; set; }
/// <summary>
/// 生日月份
/// </summary>
public int BirthMonth { get; set; }
/// <summary>
/// 性別
/// </summary>
public PersonSexTypeEnum sex;
/// <summary>
/// 人
/// </summary>
public Person person { get; set; }
}
Thread
public class MyThread
{
static void Main(string[] args)
{
Person p = new Person();
p.Name = "張三";
p.Age = 22;
p.BirthMonth = 12;
p.sex = PersonSexTypeEnum.Man;
System.Threading.Thread thrad = new System.Threading.Thread(new System.Threading.ThreadStart(p.PersonToString));
thrad.Start();
}
}
上面我們執行個體化 person 類, 使用線程thrad 調用 p.personToString 方法,這個方法在執行完畢後,線程結束, 不要理解為是調用了 thrad. Abort() abort 是停止線程,你看到這裡肯定會問,你執行個體化了Person 給Person 成員都賦值,線上程的方法中不就可以使用了嗎? 剛學習C# 的人可能都知道了 。
/// <summary>
/// 不帶參數
/// </summary>
public void PersonToString()
{
System.Threading.Thread.Sleep(60);
Console.WriteLine("no parameter ");
}
2.這裡我們介紹帶參數的啟動方法
如果要在執行個體化線程時要帶一些參數,就不能用ThreadStart委託作為建構函式的參數來執行個體化Thread了,而要parameterizedThreadStart委託,和ThreadStart 一樣的是也是線程啟動時要執行的方法,和ThreadStart不同的是,他在執行個體化時可以用一個帶有object參數的方法作為建構函式的參數,而執行個體化ThreadStart時所用到得方法是沒有參數的。
代碼
static void Main(string[] args)
{
Person p = new Person();
p.Name = "張三";
p.Age = 22;
p.BirthMonth = 12;
p.sex = PersonSexTypeEnum.Man;
//帶參數的線程
System.Threading.Thread thradparameter = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(p.PersonToString));
thradparameter.Start(p);
}
帶參數的方法
代碼
/// <summary>
/// 傳遞一個Object
/// </summary>
/// <param name="obj"></param>
public void PersonToString(object obj)
{
if (obj == null)
return;
if (obj is Person)
{
Person p = obj as Person;
System.Threading.Thread.Sleep(61);
Console.WriteLine("person name " + p.Name + "Age" + p.Age);
}
}