C# 幾種多執行緒使用總結
阿新 • • 發佈:2020-12-30
原文連結:https://www.jianshu.com/p/00b33e5cd149
1. Thread
//AMethod,為該執行緒將要執行的任務 Thread thread = new Thread(AMethod); //設定為後臺執行緒,不設定的話預設為前臺執行緒 thread.IsBackground = true; //啟動執行緒 thread.Start();
2. 通過委託來開啟執行緒
通過委託,呼叫BeginInvoke
方法來開啟一條執行緒,去執行該委託所指向的方法。
// 執行緒執行該方法 static string test1(int x, int y) { Console.WriteLine(x+ y); return x + "+"+ y; } static void Main(string[] args) { Func<int, int, string> fun1 = test1; // 通過委託來開啟執行緒執行。 倒數第二個引數是,執行緒執行完畢之後的回撥方法, 倒數第一個引數是,執行完之後,攜帶的引數。 fun1.BeginInvoke(10, 20, test1CallBack, fun1); }// 通過委託來傳遞迴調函式,會自動將該執行緒的執行結果 傳遞過來 static void test1CallBack(IAsyncResult ar) { //AsyncState 獲取所攜帶的引數,在這裡就是上面fun1.BeginInvoke(10, 20, test1CallBack, fun1); 這行程式碼中,所傳遞的fun1 Func<int, int, string> fun1 = ar.AsyncState as Func<int, int, string>;// 獲取委託所指向的方法的執行結果。 string result = fun1.EndInvoke(ar); Console.WriteLine("這就是結果" + result); }
3. 執行緒池
static void ThreadFunc3() { Console.WriteLine("--------"); // 呼叫執行緒池來執行任務。 每呼叫一次,就會開啟一條執行緒來執行該任務。 ThreadPool.QueueUserWorkItem(test3); ThreadPool.QueueUserWorkItem(test3); ThreadPool.QueueUserWorkItem(test3); ThreadPool.QueueUserWorkItem(test3); ThreadPool.QueueUserWorkItem(test3); ThreadPool.QueueUserWorkItem(test3); ThreadPool.QueueUserWorkItem(test3); ThreadPool.QueueUserWorkItem(test3); Console.WriteLine("========"); Thread.Sleep(100); } // 執行緒池呼叫的方法,需要一個object型別的引數方法,且不能有返回值 static void test3(object obj) { Thread.CurrentThread.IsBackground = false; Console.WriteLine("asdas"); }
4. Task開啟
static void ThreadMethod() { Console.WriteLine("ThreadMethod Begin" + Thread.CurrentThread.ManagedThreadId); Thread.Sleep(1000); Console.WriteLine("Thread End"); } static void continueTask(Task t) { Console.WriteLine("task is continue" + t.Id); Thread.Sleep(3000); Console.WriteLine("task is complete"); } static void Main(string[] args) { // 第一種方式開啟 //Task t = new Task(ThreadMethod); //t.Start(); //// 第二種方式開啟 //TaskFactory tf = new TaskFactory(); //tf.StartNew(ThreadMethod); Task t1 = new Task(ThreadMethod); Task t2 = t1.ContinueWith(continueTask); t1.Start(); // 開啟任務 t1, 當t1執行完畢的時候,會執行t2的任務 Console.ReadKey(); }
5. 執行緒使用問題
- 資源競爭
多個執行緒訪問同一個資源,對同一個資源做修改,會引發資料混亂。 - 死鎖
多把鎖。互相牽制。導致執行緒都互相等待解鎖。 - 案例:銀行存取款 、多視窗同時賣票
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Threading; namespace TestProject { class SaleTicket { private Thread thread1; private Thread thread2; private Thread thread3; private int ticketCount = 1000; public SaleTicket() { thread1 = new Thread(Sale); thread2 = new Thread(Sale); thread3 = new Thread(Sale); } public void Sale() { while(true) { lock(this) { if (ticketCount > 0) { ticketCount -= 1; Console.WriteLine(Thread.CurrentThread.Name + "賣了一張票,剩餘" + ticketCount); } else { Console.WriteLine(Thread.CurrentThread.Name + ":票賣完了"); break; } } } } public void StartSaleTicket() { thread1.Start(); thread2.Start(); thread3.Start(); } } }