多執行緒系列(二)之Thread類

王精靈發表於2020-08-21

在上一遍文章中講到多執行緒基礎,在此篇文章中我們來學習C#裡面Thread類。Thread類是在.net framework1.0版本中推出的API。如果對執行緒的概念還不太清楚的小夥伴請閱讀我的上一遍文章:多執行緒系列(一),多執行緒基礎

在本篇文章中新開啟一個執行緒來非同步呼叫的方法程式碼為:

        private void DoSomeThing(string btnName) {
            Console.WriteLine($"{btnName} 開始,當前執行緒id:{Thread.CurrentThread.ManagedThreadId}");
            long lResult = 0;
            for (long i = 0; i < 1_00_000_000; i++)
            {
                lResult += i;
            }
            Console.WriteLine($"{btnName} 結束,當前執行緒id:{Thread.CurrentThread.ManagedThreadId}");
        }

如何使用Thread來開啟一個新的執行緒?

方式一:基於委託ParameterizedThreadStart

                ParameterizedThreadStart method = o => this.DoSomeThing("btnThread_Click");
                Thread thread = new Thread(method);
                thread.Start();//開啟執行緒,執行委託的內容

方式二:基於委託ThreadStart

                ThreadStart method = () =>
                {
                    Thread.Sleep(3000);
                    this.DoSomeThing("btnThread_Click");
                };
                Thread thread = new Thread(method);
                thread.Start();//開啟執行緒,執行委託的內容

執行緒的暫停(掛起)、休眠、繼續、終止

thread.Suspend();//暫停,掛起執行緒,如果執行緒已經掛起,則不起作用

thread.Resume();//繼續已經掛起的執行緒

thread.Abort();//終止執行緒,會在當前執行緒中丟擲一個異常引發執行緒停止,不過會有延遲,因為執行緒屬於計算機資源,程式想停下執行緒,只能向作業系統通知(拋異常),不一定真的能停下來

Thread.ResetAbort();//終止當前執行緒,取消當前執行緒的所有請求,只能終止一次

Thread.Sleep();//使當前執行緒休眠多少毫秒再繼續執行

執行緒等待

方式一:通過thread.ThreadState獲取當前執行緒的狀態

                while (thread.ThreadState != System.Threading.ThreadState.Stopped)
                {
                    Thread.Sleep(500);
                    Console.WriteLine($"執行緒_{ thread.ManagedThreadId.ToString("00")}_正在執行中...");
                }

方式二:通過Join等待

thread.Join(); //等待執行緒thread執行完畢

thread.Join(5000); //限時等待,最多等待5000毫秒

執行緒的優先順序

thread.Priority = ThreadPriority.Highest;

設定執行緒的優先順序為最高優先順序:優先執行,但不代表優先完成,甚至說極端情況下,還有意外發生,不能通過這個來控制執行緒的執行先後順序

前臺執行緒與後臺執行緒

thread.IsBackground = false;//預設是false 前臺執行緒,程式關閉,執行緒需要計算完後才退出

thread.IsBackground = true; //關閉程式,執行緒退出

執行緒的回撥

我們希望某個執行緒在執行某個動作之後觸發另一個動作,下面是我基於Thread封裝的執行緒回撥函式

        /// <summary>
        /// 基於thread封裝一個回撥,啟動子執行緒執行動作A--不阻塞--A執行完後子執行緒會執行動作B,不阻塞
        /// </summary>
        /// <param name="method">動作A</param>
        /// <param name="action">動作B</param>
        private void ThreadWithCallBack(ThreadStart method,Action action)
        {
            ThreadStart threadStart = () =>
            {
                method.Invoke();
                action.Invoke();
            };
            new Thread(threadStart).Start();
        }

呼叫測試程式碼:

        ThreadStart method = () =>
        {
            this.DoSomeThing("btnThread_Click");
        };
        Action actionCallBack = () =>
        {
            Console.WriteLine("method 的回撥");
        };
        this.ThreadWithCallBack(method, actionCallBack);

獲取子執行緒的返回值

下面是我基於Thread封裝的獲取子執行緒的返回值函式

        T t = default(T);
        ThreadStart threadStart = () =>
        {
            t = func.Invoke();
        };
        Thread thread = new Thread(threadStart);
        thread.Start();

        return new Func<T>(() => {
            thread.Join();
            return t;
        });

呼叫測試程式碼

        Func<int> func = () => {
            return DateTime.Now.Hour;
        };
        Func<int> funcThread = this.ThreadWithReturn<int>(func);//非阻塞
        int res =  funcThread.Invoke();//阻塞

 在下一篇中,會繼續講到執行緒池

相關文章