C# Thread 執行緒
程式都會有一個主處理序
例如,在同一個主處理序,可能同時會需要送出多筆訂單、讀取大型檔案等項目要排隊
在這主要的處理序,可以額外建立新的執行緒,可以將指定的任務交給新的執行緒獨立處理
通常,需要長時運算、 等待回應的流程,就會透過建立新的執行緒來獨立運算,避免影響到其他流程
載入空間命名
using System.Threading;
ThreadStart 執行緒
首先,介紹ThreadStart,可以直接委派執行緒至無回傳值的物件
class Program
{
static void Main(string[] args)
{
Program mProgram = new Program();
mProgram.ProvideMission();
Console.ReadKey();
}
//指派任務
private void ProvideMission()
{
//指定委派物件
ThreadStart MissionA_Tg = new ThreadStart(MissionA);
//建立A任務執行緒
Thread MissionA_Thread = new Thread(MissionA_Tg);
MissionA_Thread.Name = "Mission A";
//指定委派物件
ThreadStart MissionB_Tg = new ThreadStart(MissionB);
//建立B任務執行緒
Thread MissionB_Thread = new Thread(MissionB_Tg);
MissionB_Thread.Name = "Mission B";
//啟動執行緒
MissionA_Thread.Start();
MissionB_Thread.Start();
NormalProcess();
}
//任務A
private void MissionA()
{
for (int i = 0; i < 1000; i++)
{
if (i % 2 != 0)
{
Console.WriteLine("A" + i);
}
}
}
//任務B
private void MissionB()
{
for (int i = 0; i < 1000; i++)
{
if (i % 2 == 0)
{
Console.WriteLine("B" + i);
}
}
}
//Normal
private void NormalProcess()
{
Console.WriteLine("This is normal process ========================");
}
}
ParameterizedThreadStart 執行緒
ParameterizedThreadStart 執行緒可以將參數值傳給委派物件
class Program
{
static void Main(string[] args)
{
Program mProgram = new Program();
mProgram.ProvideMission();
Console.ReadKey();
}
//指派任務
private void ProvideMission()
{
//指定委派物件
ParameterizedThreadStart MissionA_Tg = new ParameterizedThreadStart(MissionA);
//建立A任務執行緒
Thread MissionA_Thread = new Thread(MissionA_Tg);
MissionA_Thread.Name = "Mission A";
//指定委派物件
ParameterizedThreadStart MissionB_Tg = new ParameterizedThreadStart(MissionB);
//建立B任務執行緒
Thread MissionB_Thread = new Thread(MissionB_Tg);
MissionB_Thread.Name = "Mission B";
//啟動執行緒
MissionA_Thread.Start(10);
MissionB_Thread.Start(10);
NormalProcess();
}
//任務A
private void MissionA(object value)
{
int num = Convert.ToInt32(value);
for (int i = 0; i < num; i++)
{
if (i % 2 != 0)
{
Console.WriteLine("A" + i);
Thread.Sleep(1000);
}
}
}
//任務B
private void MissionB(object value)
{
int num = Convert.ToInt32(value);
for (int i = 0; i < num; i++)
{
if (i % 2 == 0)
{
Console.WriteLine("B" + i);
Thread.Sleep(2000);
}
}
}
//Normal
private void NormalProcess()
{
Console.WriteLine("This is normal process ========================");
}
}
暫停 Thread.Sleep
在執行緒執行過程,可以透過Thread.Sleep讓執行緒暫停指定的毫秒
class Program
{
static void Main(string[] args)
{
Program mProgram = new Program();
mProgram.ProvideMission();
Console.ReadKey();
}
//指派任務
private void ProvideMission()
{
//指定委派物件
ParameterizedThreadStart MissionA_Tg = new ParameterizedThreadStart(MissionA);
//建立A任務執行緒
Thread MissionA_Thread = new Thread(MissionA_Tg);
MissionA_Thread.Name = "Mission A";
//指定委派物件
ParameterizedThreadStart MissionB_Tg = new ParameterizedThreadStart(MissionB);
//建立B任務執行緒
Thread MissionB_Thread = new Thread(MissionB_Tg);
MissionB_Thread.Name = "Mission B";
//啟動執行緒
MissionA_Thread.Start(10);
MissionB_Thread.Start(10);
NormalProcess();
}
//任務A
private void MissionA(object value)
{
int num = Convert.ToInt32(value);
for (int i = 0; i < num; i++)
{
if (i % 2 != 0)
{
Console.WriteLine("A" + i);
Thread.Sleep(1000);
}
}
}
//任務B
private void MissionB(object value)
{
int num = Convert.ToInt32(value);
for (int i = 0; i < num; i++)
{
if (i % 2 == 0)
{
Console.WriteLine("B" + i);
Thread.Sleep(2000);
}
}
}
//Normal
private void NormalProcess()
{
Console.WriteLine("This is normal process ========================");
}
}
封鎖/阻塞 Thread.Join()
通常我們認知的Join是連結的意思,但是在C# Thread.Join 的意思是
可以封鎖指定的執行緒,直到執行緒執行完畢
主要用於控制順序,等封鎖的執行緒執行完畢,主處理序才會繼續往下走
class Program
{
private Thread MissionA_Thread;
private Thread MissionB_Thread;
static void Main(string[] args)
{
Program mProgram = new Program();
mProgram.ProvideMission();
Console.WriteLine("Blocks the calling MissionA thread");
mProgram.MissionA_Thread.Join();
Console.WriteLine("MissionA thread terminates");
Console.ReadKey();
}
//指派任務
private void ProvideMission()
{
//指定委派物件
ParameterizedThreadStart MissionA_Tg = new ParameterizedThreadStart(MissionA);
//建立A任務執行緒
MissionA_Thread = new Thread(MissionA_Tg);
MissionA_Thread.Name = "Mission A";
//指定委派物件
ParameterizedThreadStart MissionB_Tg = new ParameterizedThreadStart(MissionB);
//建立B任務執行緒
MissionB_Thread = new Thread(MissionB_Tg);
MissionB_Thread.Name = "Mission B";
//啟動執行緒
MissionA_Thread.Start(10);
MissionB_Thread.Start(10);
NormalProcess();
}
//任務A
private void MissionA(object value)
{
int num = Convert.ToInt32(value);
for (int i = 0; i < num; i++)
{
if (i % 2 != 0)
{
Console.WriteLine("A" + i);
Thread.Sleep(1000);
}
}
}
//任務B
private void MissionB(object value)
{
int num = Convert.ToInt32(value);
for (int i = 0; i < num; i++)
{
if (i % 2 == 0)
{
Console.WriteLine("B" + i);
Thread.Sleep(2000);
}
}
}
//Normal
private void NormalProcess()
{
Console.WriteLine("This is normal process ========================");
}
}
Lock 鎖定
Lock 可以針對委派至同一個物件時,控制鎖定資源
當多個執行緒執行同一物件,只要其中一個先執行,其他的就要排隊等他執行完
class Program
{
private Thread MissionB_Thread;
static void Main(string[] args)
{
Program mProgram = new Program();
mProgram.ProvideMission();
Console.ReadKey();
}
//指派任務
private void ProvideMission()
{
//指定委派物件
ParameterizedThreadStart MissionA_Tg1 = new ParameterizedThreadStart(MissionA);
ParameterizedThreadStart MissionA_Tg2 = new ParameterizedThreadStart(MissionA);
ParameterizedThreadStart MissionA_Tg3 = new ParameterizedThreadStart(MissionA);
//建立A任務執行緒
Thread MissionA_Thread1 = new Thread(MissionA_Tg1);
Thread MissionA_Thread2 = new Thread(MissionA_Tg2);
Thread MissionA_Thread3 = new Thread(MissionA_Tg3);
MissionA_Thread1.Name = "Mission A1";
MissionA_Thread2.Name = "Mission A2";
MissionA_Thread3.Name = "Mission A3";
//指定委派物件
ParameterizedThreadStart MissionB_Tg = new ParameterizedThreadStart(MissionB);
//建立B任務執行緒
MissionB_Thread = new Thread(MissionB_Tg);
MissionB_Thread.Name = "Mission B";
//啟動執行緒
MissionA_Thread1.Start("Aa");
MissionA_Thread2.Start("Aaa");
MissionA_Thread3.Start("Aaaa");
MissionB_Thread.Start(10);
NormalProcess();
}
//任務A
private void MissionA(object name)
{
string txt = Convert.ToString(name);
for (int i = 0; i < 10; i++)
{
if (i % 2 != 0)
{
lock (this)
{
Console.WriteLine(txt + i);
Thread.Sleep(1000);
}
}
}
}
//任務B
private void MissionB(object value)
{
int num = Convert.ToInt32(value);
for (int i = 0; i < num; i++)
{
if (i % 2 == 0)
{
Console.WriteLine("B" + i);
Thread.Sleep(2000);
}
}
}
//Normal
private void NormalProcess()
{
Console.WriteLine("This is normal process ========================");
}
}
Monitor 監控
Monitor 監控,提供更彈性的方式來控制執行緒流程
其中提供幾個靜態方法
Monitor.Enter : 開始監控 Monitor.Wait : 暫停執行緒 Monitor.Pluse : 喚醒被暫停的執行緒 Monitor.Exit : 結束監控
class Program
{
private Thread MissionB_Thread;
static void Main(string[] args)
{
Program mProgram = new Program();
mProgram.ProvideMission();
Console.ReadKey();
}
//指派任務
private void ProvideMission()
{
//指定委派物件
ParameterizedThreadStart MissionA_Tg = new ParameterizedThreadStart(MissionA);
//建立A任務執行緒
Thread MissionA_Thread = new Thread(MissionA_Tg);
MissionA_Thread.Name = "Mission A";
//指定委派物件
ParameterizedThreadStart MissionB_Tg = new ParameterizedThreadStart(MissionB);
//建立B任務執行緒
MissionB_Thread = new Thread(MissionB_Tg);
MissionB_Thread.Name = "Mission B";
//啟動執行緒
MissionA_Thread.Start(10);
MissionB_Thread.Start(10);
//暫停主執行緒
MissionB_Thread.Join();
NormalProcess();
//開始監控
Monitor.Enter(this);
//喚醒被暫停的執行緒
Monitor.Pulse(this);
//結束監控
Monitor.Exit(this);
}
//任務A
private void MissionA(object value)
{
//開始監控
Monitor.Enter(this);
int num = Convert.ToInt32(value);
for (int i = 0; i < num; i++)
{
if (i == 5)
{
//暫停執行緒
Monitor.Wait(this);
}
Console.WriteLine("A" + i);
Thread.Sleep(1000);
}
//結束監控
Monitor.Exit(this);
}
//任務B
private void MissionB(object value)
{
int num = Convert.ToInt32(value);
for (int i = 0; i < num; i++)
{
Console.WriteLine("B" + i);
Thread.Sleep(2000);
}
}
//Normal
private void NormalProcess()
{
Console.WriteLine("This is normal process ========================");
}
}
Interrupt 中斷執行緒
在執行緒運作時,可以透過 Interrupt 阻斷執行緒
並且可以透過 try catch 捕捉例外
當指定執行緒被終止時,Join也會立即執行完畢
class Program
{
private Thread MissionA_Thread;
private Thread MissionB_Thread;
static void Main(string[] args)
{
Program mProgram = new Program();
mProgram.ProvideMission();
Console.ReadKey();
}
//指派任務
private void ProvideMission()
{
//指定委派物件
ParameterizedThreadStart MissionA_Tg = new ParameterizedThreadStart(MissionA);
//建立A任務執行緒
MissionA_Thread = new Thread(MissionA_Tg);
MissionA_Thread.Name = "Mission A";
//指定委派物件
ParameterizedThreadStart MissionB_Tg = new ParameterizedThreadStart(MissionB);
//建立B任務執行緒
MissionB_Thread = new Thread(MissionB_Tg);
MissionB_Thread.Name = "Mission B";
//啟動執行緒
MissionA_Thread.Start(10);
MissionB_Thread.Start(10);
//暫停主執行緒
MissionB_Thread.Join();
NormalProcess();
}
//任務A
private void MissionA(object value)
{
try
{
int num = Convert.ToInt32(value);
for (int i = 0; i < num; i++)
{
if (i == 5)
{
//中斷執行緒
MissionA_Thread.Interrupt();
}
Console.WriteLine("A" + i);
Thread.Sleep(1000);
}
}catch (ThreadInterruptedException)
{
//
Console.WriteLine(Thread.CurrentThread.Name);
}
}
//任務B
private void MissionB(object value)
{
try {
int num = Convert.ToInt32(value);
for (int i = 0; i < num; i++)
{
if (i > 6)
{
//中斷執行緒
MissionB_Thread.Interrupt();
}
Console.WriteLine("B" + i);
Thread.Sleep(2000);
}
}
catch (ThreadInterruptedException)
{
//捕捉中斷執行緒拋出的例外
Console.WriteLine(Thread.CurrentThread.Name+"Is Stop");
}
}
//Normal
private void NormalProcess()
{
Console.WriteLine("This is normal process ========================");
}
}
Abort 手動終止執行緒
在執行緒啟動過程,可以透過 Abort 強制停止
if(MissionA_Thread.IsAlve)
{
MissionA_Thread.Abort();
}
IsBackground 背景執行
在多數執行緒設計,都會需要持續執行、並且在主要程式結束時跟著停止
這時只要將 IsBackground 設定為 true 就可以達到背景執行,程式結束就跟著結束
//指定委派物件
ParameterizedThreadStart MissionA_Tg = new ParameterizedThreadStart(MissionA);
//建立A任務執行緒
MissionA_Thread = new Thread(MissionA_Tg);
//設定為背景執行
MissionA_Thread.IsBackground = true;
MissionA_Thread.Start();