//前台線程和后台線程唯一區別就是:應用程序必須運行完所有的前台線程才可以退出;
//而對於后台線程,應用程序則可以不考慮其是否已經運行完畢而直接退出,
//所有的后台線程在應用程序退出時都會自動結束。
通過匿名委托或Lambda表達式來為Thread的構造方法賦值
Thread thread3 = new Thread(delegate() { Console.WriteLine("匿名委托"); }); thread3.Start(); Thread thread4 = new Thread(( ) => { Console.WriteLine("Lambda表達式"); }); thread4.Start();
二、 定義一個線程類
我們可以將Thread類封裝在一個MyThread類中,以使任何從MyThread繼承的類都具有多線程能力。MyThread類的代碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace MyThread { abstract class MyThread { Thread thread = null; abstract public void run(); public void start() { if (thread == null) thread = new Thread(run); thread.Start(); } } }
可以用下面的代碼來使用MyThread類。
class NewThread : MyThread { override public void run() { Console.WriteLine("使用MyThread建立並運行線程"); } } static void Main(string[] args) { NewThread nt = new NewThread(); nt.start(); }
如果使用在第二節定義的MyThread類,傳遞參數會顯示更簡單,代碼如下:
class NewThread : MyThread { private String p1; private int p2; public NewThread(String p1, int p2) { this.p1 = p1; this.p2 = p2; } override public void run() { Console.WriteLine(p1); Console.WriteLine(p2); } } NewThread newThread = new NewThread("hello world", 4321); newThread.start();
EventWaitHandle(等待事件句柄)
EventWaitHandle是一個在線程處理上的類,它可以和WaitHandle配合使用完成多線程任務等待調度,並且在主線程中統一處理想要的結果。
private List<string> test() { List<string> list = new List<string>(); //創建等待事件句柄集合 var watis = new List<EventWaitHandle>(); for (int i = 0; i < 5; i++) { //創建句柄 true終止狀態 var handler = new ManualResetEvent(false); watis.Add(handler); //將要執行的方法參數化 ParameterizedThreadStart start = new ParameterizedThreadStart(selectData); //創建線程,傳入線程參數 Thread t = new Thread(start); //啟動線程 t.Start(new Tuple<int, EventWaitHandle, List<string>>(i, handler,list)); } //等待句柄 WaitHandle.WaitAll(watis.ToArray()); return list; }
-
首先創建了一個EventWaitHandle的list,這個list將用於來添加所有的需要執行的等待事件句柄
-
然后將需要參與等待的任務(一個方法)參數化傳入線程初始化的構造
-
在線程啟動時,將與之對應的EventWaitHandle子類ManualResetEvent的對象傳入需要調用的任務(方法)中
-
最后使用WaitHandle.WaitAll執行所有的等待事件句柄
private static void selectData(object param) { Tuple<int, EventWaitHandle,List<string>> t = (Tuple<int, EventWaitHandle,List<string>>)param; Console.WriteLine(Thread.CurrentThread.Name + "執行開始"); //sleep線程,模擬查詢業務 if (t.Item1 == 0) { Thread.Sleep(1500); t.Item3.Add("這是第0個線程添加的內容"); } else if (t.Item1 == 1) { Thread.Sleep(1234); t.Item3.Add("這是第1個線程添加的內容"); } else if (t.Item1 == 2) { Thread.Sleep(1759); t.Item3.Add("這是第2個線程添加的內容"); } //將事件狀態設置為有信號,從而允許一個或多個等待線程繼續執行。 t.Item2.Set(); Console.WriteLine(Thread.CurrentThread.Name + "執行結束"); }
-
在等待句柄任務中執行查詢,並將結果加入數據list中
-
最后在任務的最后(執行完成)將等待事件句柄對象Set(),這個方法將發出一個信號(暫時理解為通知WaitHandle當前的等待事件句柄執行完成)
作者:methodname
鏈接:https://www.jianshu.com/p/64670b155b1c
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權並注明出處。
Lock鎖
lock是一種比較好用的簡單的線程同步方式,它是通過為給定對象獲取互斥鎖來實現同步的。它可以保證當一個線程在關鍵代碼段的時候,另一個線程不會進來,它只能等待,等到那個線程對象被釋放,也就是說線程出了臨界區。
public void Function() { object lockThis = new object (); lock (lockThis) { // Access thread-sensitive resources. } }
lock關鍵字的用法和用途。
using System; using System.Threading; namespace ThreadSimple { internal class Account { int balance; //余額 Random r=new Random(); internal Account(int initial) { balance=initial; } internal int Withdraw(int amount) //取回、取款 { if(balance<0) { //如果balance小於0則拋出異常 throw new Exception("NegativeBalance");//負的 余額 } //下面的代碼保證在當前線程修改balance的值完成之前 //不會有其他線程也執行這段代碼來修改balance的值 //因此,balance的值是不可能小於0的 lock(this) { Console.WriteLine("CurrentThread:"+Thread.CurrentThread.Name); //如果沒有lock關鍵字的保護,那么可能在執行完if的條件判斷(成立)之后 //另外一個線程卻執行了balance=balance-amount修改了balance的值 //而這個修改對這個線程是不可見的,所以可能導致這時if的條件已經不成立了 //但是,這個線程卻繼續執行 balance=balance-amount,所以導致balance可能小於0 if(balance>=amount) { Thread.Sleep(5); balance=balance-amount; return amount; } else { return 0; //transactionrejected } } } internal void DoTransactions()//取款事務 { for (int i = 0; i < 100; i++) { Withdraw(r.Next(-50, 100)); } } } internal class Test { static internal Thread[] threads=new Thread[10]; public static void Main() { Account acc=new Account(0); for(int i=0;i<10;i++) { Thread t=new Thread(new ThreadStart(acc.DoTransactions)); threads[i]=t; } for (int i = 0; i < 10; i++) { threads[i].Name = i.ToString(); } for (int i = 0; i < 10; i++) { threads[i].Start(); Console.ReadLine(); } } } }