1. 程式人生 > 其它 >C# 實現執行緒的常用幾種方式

C# 實現執行緒的常用幾種方式

前言

  在各個開發語言中,執行緒是避免不了的,或許通過表象看不出來,但是真的無處不在。就比如一個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 執行緒池實現

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 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#中使用多執行緒常用的幾種方式,這裡只是簡單的彙總方式,沒有深入分析,後續將針對模組進行分析。