C#中異步多線程的實現方式


線程是操作系統能夠進行運算調度的最小單位。它被包含在進程之中,是進程中的實際運作單位。一條線程指的是進程中一個單一順序的控制流,一個進程中可以並發多個線程,每條線程並行執行不同的任務。

一.通過委托的方式

委托中的Invoke方法完成一個委托方法的封送,在Invoke封送的方法被執行完畢前,Invoke方法不會返回,從而調用者線程將被阻塞。委托中的BeginInvoke方法是從ThreadPool取出一個線程來執行這個方法,以獲得異步執行效果的。

        public delegate int AddDelegate(int a, int b);  //定義一個委托對象 static void Main(string[] args)
        {
            Console.WriteLine("start");
            AddDelegate d1 = Add;
            //異步回調方法,異步方法執行完可以選擇執行這個方法
            AsyncCallback cab = t =>
            {
                //Console.WriteLine(d1.EndInvoke(t));
                Console.WriteLine(t.AsyncState);    //可以獲取傳遞過來的參數
                Console.WriteLine(t.IsCompleted);
            };

            IAsyncResult ar = d1.BeginInvoke(5,2,cab,12);    //前兩個參數為引用方法傳遞的參數,cab為上面的回調方法,12為回調方法中的參數,執行BeginInvoke會返回一個IAsyncResult對象        
            Thread.Sleep(2000);
            int result = d1.EndInvoke(ar);           //該方法返回委方法中的真正返回值,該方法會阻塞主線程一直到異步執行完,EndInvoke只能被執行一次 
            Console.WriteLine("結果:"+result);

        }
        public static int Add(int a,int b)
        {
            return a + b;
        }       

 二.通過Thread類

 C#中的Thread類主要提供四個構造方法,ThreadStart是一個無參的委托,意味着我們能傳遞一個無參的方法進去。ParameterizedThreadStart是一個只有一個參數,參數類型為object的委托,我們可以傳一個一個參數,參數類型為object的類型進去

     static void Main(string[] args)
        {
            //ThreadStart start1 = AddNoParms;
            //Thread thread1 = new Thread(start1);
            Thread thread1 = new Thread(AddNoParms);  //簡化寫法,直接傳遞與委托方法簽名對應的方法
            Thread thread2 = new Thread(AddHasParms); //有參的形式
            thread1.Start();//開啟這個線程
            thread2.Start("thread2");  //開啟有參的Thread線程
            thread1.Name = "thread1";       //獲取或設置線程的名稱。
            thread1.IsBackground = true;   //獲取或設置一個值,該值指示某個線程是否為后台線程。
            Thread.Sleep(2000); //讓線程暫停一段時間。
            thread1.Abort();    //銷毀線程
            Console.WriteLine(thread1.IsAlive);     //獲取線程狀態


            //獲取異步回調的返回值
            int returndata = 0;     //聲明一個變量用來接收異步方法執行的返回值
            ThreadStart threadstart = new ThreadStart
                (() =>{
                        returndata = Add(1, 2);
                        AddNoParms();
                    });
            Thread thread3 = new Thread(threadstart);
            thread3.Start();
            Console.WriteLine(returndata);
        }
        public static void AddHasParms(object str)
        {
            Console.WriteLine(str);
        }

        public static void AddNoParms()
        {
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
            Console.WriteLine("add");
        }
        public static int Add(int a,int b)
        {
            return a + b;
        }

 Thread類中還提供了許多屬性和方法供我們使用

  //屬性
      IsAlive   //獲取一個值,該值指示當前線程的執行狀態。
      IsBackground   //獲取或設置一個值,該值指示某個線程是否為后台線程。前台進程跟后台進程的區別:程序關閉時,后台線程直接關閉,但前台線程會執行完后關閉。通過Thread類新建線程默認為前台線程。其他方式創建的都是后台線程。
      IsThreadPoolThread    //獲取一個值,該值指示線程是否屬於托管線程池。
      Priority    //獲取或設置一個值,該值指示線程的調度優先級。
  //方法
      Abort    //在調用此方法的線程上引發 ThreadAbortException,以開始終止此線程的過程。調用此方法通常會終止線程。
      Join       //阻塞調用線程,直到某個線程終止為止。此方法有不同的重載形式
      ResetAbort    //取消為當前線程請求的 Abort。

 三.ThreadPool

ThreadPool類會在線程的托管池中重用已有的線程,一個應用程序最多只能有一個線程池,可以通過QueueUserWorkItem方法將工作函數排入進程池。QueueUserWorkItem有兩個構造函數,WaitCallback是一個只有一個參數,參數類型為object的委托,我們可以傳一個參數,參數類型為object的對象進行實例化

     static void Main(string[] args)
        {
       ThreadPool.SetMinThreads(1,1);
       ThreadPool.SetMaxThreads(1,5);
//調用方式一 用WaitCallback這個委托進行實例化 WaitCallback waitCallback = new WaitCallback(AddHasParms); ThreadPool.QueueUserWorkItem(waitCallback, "helloworld"); //調用方式二 傳遞與WaitCallback對應的方法進行實例化 ThreadPool.QueueUserWorkItem(AddHasParms,"helloworld"); //調用方法三 通過WaitCallback相對應的匿名方法,在匿名方法中進行調用 ThreadPool.QueueUserWorkItem(n=> { AddNoParms(); AddHasParms("helloworld"); }); } public static void AddHasParms(object str) { Console.WriteLine(Thread.CurrentThread.ManagedThreadId); Console.WriteLine(str); } public static void AddNoParms() { Console.WriteLine(Thread.CurrentThread.ManagedThreadId); }

 四.Task

     static void Main(string[] args)
        {
            //方式一   無返回值時
            Task task1 = new Task(AddHasParms, "helloworld");
            task1.Start();
            Task.WaitAll(task1);    //等待所有任務結束  
                    //有返回值時
            Task<int> task2 = new Task<int>(Add, "obj");
            task2.Start();
            Console.WriteLine(task2.Result);       //打印返回值

            //方式二    通過Run方法創建  無返回值
            Task.Run(() => AddHasParms("hello"));
            //無返回值時
            Task<int> task3 = Task.Run(() => Add("obj"));
            Console.WriteLine(task3.Result);

            //方式三 無返回值時
            Task.Factory.StartNew(() => AddHasParms("helloworld"));
            Task.WaitAll();
            //有返回值時
            var task4=Task.Factory.StartNew(() => Add("obj"));
            Console.WriteLine(task4.Result);


        }
        public static void AddHasParms(object str)
        {
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
            Console.WriteLine(str);
        }
        public static int Add(object a)
        {
            return  1;
        }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM