1. 程式人生 > 實用技巧 >C# 幾種多執行緒使用總結

C# 幾種多執行緒使用總結

原文連結: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. 執行緒使用問題

  1. 資源競爭
    多個執行緒訪問同一個資源,對同一個資源做修改,會引發資料混亂。
  2. 死鎖
    多把鎖。互相牽制。導致執行緒都互相等待解鎖。
  3. 案例:銀行存取款 、多視窗同時賣票
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();
        }
    }
}