前言
在各個開發語言中,線程是避免不了的,或許通過表象看不出來,但是真的無處不在。就比如一個Web程序,平時或許只注重增刪改查的開發,根本沒有編寫相關多線程的的代碼,但是請求內部的時候,已經分配了對應線程進行處理了,以下簡單說說C#中使用線程的幾種方式,詳細使用后續繼續記錄。
Thread類實現
Thread類的實現方式,在C# .NetFramework剛出的時候就已經存在了,起初剛開始的程序員都使用這種方式,但經歷后面幾個.NetFramework的版本更新,實現方式變的更多了。
public void TestThread() { //這里需要注意的是:在C#中線程是離不開委托的 //創建了一個線程對象,這里構造函數提供兩類,一種不帶參數的,一種是帶參數的 Thread thread = new Thread( TestAction); //設置線程相關屬性 thread.IsBackground = true; thread.Name = "Test"; //啟動線程 thread.Start(); } /// <summary> /// 線程執行的方法 /// </summary> private void TestAction() { //這里實現線程處理的相關業務 Console.WriteLine($"子線程Thread({Thread.CurrentThread.Name})執行相關業務操作....{Thread.CurrentThread.ManagedThreadId}"); }
運行結果:
ThreadPool 線程池實現
using System; using System.Collections.Generic; using System.Text; using System.Threading; namespace MutltiThreadImplement { /// <summary> /// ThreadPool 池化線程,避免頻繁的申請和釋放消耗資源;之前Thread每次都要申請和釋放。 /// </summary> public class ThreadPoolImplement { public void TestThreadPool() { //可以設置相關屬性 ThreadPool.SetMinThreads(5,10); ThreadPool.SetMaxThreads(6, 10); //通過線程池自動分配線程執行對應的業務功能 ThreadPool.QueueUserWorkItem(TestAction); } private void TestAction(object state) { //這里實現線程處理的相關業務 Console.WriteLine($"子線程Thread({Thread.CurrentThread.Name})執行相關業務操作....{Thread.CurrentThread.ManagedThreadId}"); } } }
運行結果:
ThreadPool的使用是不是感覺比較簡單,但是就是因為太簡單了,在業務中有些需求得不到滿足,比如試着控制線程順序;
Delegate 實現的多線程
public void TestDelegateThread() { //定義一個強類型委托, 可以自定義委托 Action action = TestAction; //開始異步操作,其實內部是開啟了子線程,看線程id不一樣就明白了 IAsyncResult asyncResult = action.BeginInvoke(CallBack, null); //可以根據返回對象的一些屬性和方法進行判斷和業務邏輯執行 具體可以查看相關文檔 //asyncResult.IsCompleted; //判讀是否執行完成 //asyncResult.AsyncWaitHandle.WaitOne(); //阻塞當前線程,直到收到信號量 } private void TestAction() { //這里實現線程處理的相關業務 Console.WriteLine($"子線程Thread({Thread.CurrentThread.Name})執行相關業務操作....{Thread.CurrentThread.ManagedThreadId}"); } /// <summary> /// 子線程執行完成時的回調 /// </summary> private void CallBack(IAsyncResult ar) { Console.WriteLine($"子線程{Thread.CurrentThread.ManagedThreadId}執行完畢"); }
運行結果:
注: 這種方式在.NetCore環境不支持,提示平台不支持。
BackGroundWorker 實現
BackgroundWorker backgroundWorker = new BackgroundWorker(); public void TestBackGroundWorker() { //這里使用的是事件的方式綁定業務處理方法 backgroundWorker.DoWork += TestAction; //可以綁定一些事件 使用很簡單,可以不需要綁定以下事件和設置屬性就可以執行,根據需要進行綁定 //執行完成事件 backgroundWorker.RunWorkerCompleted += BackgroundWorker_RunWorkerCompleted; backgroundWorker.ProgressChanged += BackgroundWorker_ProgressChanged; backgroundWorker.WorkerReportsProgress = true;//只有執行這個屬性之后才能進行ProgressChanged觸發 //開始執行操作 backgroundWorker.RunWorkerAsync(); } /// <summary> /// 觸發事件之后的業務處理 /// </summary> private void BackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) { Console.WriteLine("可以在這里更新UI線程上的東西...."); } /// <summary> /// 觸發事件之后的業務處理 /// </summary> private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { Console.WriteLine($"子線程{Thread.CurrentThread.ManagedThreadId}執行完成!!!"); } private void TestAction(object sender, DoWorkEventArgs e) { //這里實現線程處理的相關業務 Console.WriteLine($"子線程Thread({Thread.CurrentThread.Name})執行相關業務操作....{Thread.CurrentThread.ManagedThreadId}"); //在業務方法中執行ReportProgress方法會觸發ProgressChanged事件 backgroundWorker.ReportProgress(10); Console.WriteLine($"子線程Thread({ Thread.CurrentThread.ManagedThreadId})執行相關業務操作結束"); }
運行結果:
BackgroundWorker 這種方式比較適應於窗體應用程序。
Task 實現多線程
/// <summary> /// Task 實現多線程, 目前為止,Task方式是大家都比較推薦的方式 /// </summary> public void TestTask() { //創建一個Task實例 Task task = new Task(TestAction); //開始任務 task.Start(); } private void TestAction() { //這里實現線程處理的相關業務 Console.WriteLine($"子線程Thread({Thread.CurrentThread.Name})執行相關業務操作....{Thread.CurrentThread.ManagedThreadId}"); }
運行結果
Task實現多線程的方式是大家一致推薦的,俗稱最佳實踐。
Parallel實現多線程
/// <summary> /// Parallel 是對Task的進一步封裝,但會阻塞主線程,主線程會參與業務邏輯處理 /// </summary> public class ParallelImplement { public void TestParallel() { //分配線程執行業務邏輯, Invoke可傳多個業務處理,內部會自動分配線程處理 Parallel.Invoke(TestAction); } private void TestAction() { //這里實現線程處理的相關業務 Console.WriteLine($"子線程Thread({Thread.CurrentThread.Name})執行相關業務操作....{Thread.CurrentThread.ManagedThreadId}"); } }
運行結果:
根據運行結果得出結論,主線程參與業務邏輯處理中,會阻塞線程, Parallel可根據業務進行選擇使用。
總結
以上基本上就是C#中使用多線程常用的幾種方式,這里只是簡單的匯總方式,沒有深入分析,后續將針對模塊進行分析。