天天看點

1.異步

01.異步任務

class Program
    {
       
        static void Main(string[] args)
        {
            Simple simple=new Simple();
            simple.DoRun();
            Console.WriteLine("main");
            Console.ReadKey();
        }



        class Simple
        {
            Stopwatch sw=new Stopwatch();

            public void DoRun()
            {
                Console.WriteLine("Caller: Before call");
                ShowDealyAsync();
                Console.WriteLine("Caller: After call");
            }

            private async void ShowDealyAsync()
            {
                sw.Start();
                Console.WriteLine("  Before Delay: {0}", sw.ElapsedMilliseconds);
                await Task.Delay(3000); //異步延時
                Console.WriteLine("延時觸發"); 
                Console.WriteLine(" After Delay : {0}", sw.ElapsedMilliseconds);//後續部分
            }

        }

    }      
class Program
    {
        static void Main(string[] args)
        {
            AsyncTaskOne();
            for (int i = 0; i < 10; i++)
            {
               // Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString()); //目前線程的ID
                Thread.Sleep(500);
                Console.WriteLine($"main:+{i}");   
            }
            Console.ReadKey();
        }

        private async static void AsyncTaskOne()
        {
            await Task.Run(() =>
            {
               // Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString());
                for (int i = 0; i < 10; i++)
                {
                    Thread.Sleep(500);
                    Console.WriteLine($"{Thread.CurrentThread.Name}:+{i}");
                    Console.WriteLine();
                }
            });
        }

    }      
1.異步

03.開啟一個任務的三種方式

static void Main(string[] args)
        {
            AsyncTask();
            Console.ReadKey();
        }

        /// <summary>
        /// 開啟一個任務的三種方式
        /// </summary>
        private static void AsyncTask()
        {
            //1.new方式執行個體化一個Task,需要通過Start方法啟動
            Task task1=new Task(() =>
            {
                Thread.Sleep(500);
                Console.WriteLine($"task1的線程ID為{Thread.CurrentThread.ManagedThreadId}");
            });
            task1.Start();
            //2.Task.Factory.StartNew(Action action)建立和啟動一個Task
            Task task2 = Task.Factory.StartNew(() =>
            {
                Thread.Sleep(800);
                Console.WriteLine($"task2的線程ID為{Thread.CurrentThread.ManagedThreadId}");
            });
            //3.Task.Run(Action action)将任務放線上程池隊列,傳回并啟動一個Task
            Task task3=Task.Run(() =>
            {
                Thread.Sleep(1000);
                Console.WriteLine($"task3的線程ID為{Thread.CurrentThread.ManagedThreadId}");
            });
            Console.WriteLine("Main");
        }      
1.異步

04.建立有傳回值的Task

task.Resut擷取結果時會阻塞線程,即如果task沒有執行完成,會等待task執行完成擷取到Result,然後再執行後邊的代碼,

/// <summary>
        /// 帶有傳回值
        /// </summary>
        private static void AsyncTaskTwo()
        {
            Task<string> task1 = new Task<string>(() => $"task1的線程ID是{Thread.CurrentThread.ManagedThreadId}");
            task1.Start();
            Task<string> task2=Task.Factory.StartNew(() => { return $"task2的線程ID是{Thread.CurrentThread.ManagedThreadId}"; },TaskCreationOptions.LongRunning);
            Task<string> task3 = Task<string>.Run(() =>
            {
                return $"task1的線程ID是{Thread.CurrentThread.ManagedThreadId}";
            });
            Console.WriteLine("主線程");
            Console.WriteLine("task1結果:" + task1.Result);
            Console.WriteLine("task2結果:" + task2.Result);
            Console.WriteLine("task3結果:" + task3.Result);
        }      
1.異步

05。同步執行

static void Main(string[] args)
        {
            AsyncTaskThree();
            Console.WriteLine("主線程ID:"+ Thread.CurrentThread.ManagedThreadId);
            Console.ReadKey();
        }


        //task.RunSynchronously() 用于同步執行Task任務

        private static void AsyncTaskThree()
        {
            Task task=new Task(() =>
            {
                Thread.Sleep(500);
                Console.WriteLine("執行Task結束!");
            });
            //同步執行,task會阻塞主線程
            task.RunSynchronously();

        }      
1.異步

06.

Task的Wait/WaitAny/WaitAll

task.Wait() 表示等待task執行完畢,功能類似于thead.Join(); Task.WaitAll(Task[] tasks) 表示隻有所有的task都執行完成了再解除阻塞; Task.WaitAny(Task[] tasks) 表示隻要有一個task執行完畢就解除阻塞

static void Main(string[] args)
        {
            ThreadblockTwo();
            Console.WriteLine("主線程執行完畢!");
            Console.WriteLine("主線程ID:"+ Thread.CurrentThread.ManagedThreadId);
            Console.ReadKey();
        }
private static void ThreadblockTwo()
        {
            Task task1=new Task(() =>
            {
                Thread.Sleep(2000);
                Console.WriteLine("線程1執行完畢!");
            });
            task1.Start();
            Task task2 = new Task(() =>
            {
                Thread.Sleep(3000);
                Console.WriteLine("線程2執行完畢!");
            });
            task2.Start();
            //阻塞主線程。task1,task2都執行完畢再執行主線程
            //task1.Wait(); task2.Wait(); //可以實作相同的功能
            Task.WaitAll(new Task[]{task1,task2});
            //Task.WaitAny(); //task 執行完畢就會解除線程阻塞

        }      
1.異步

07.

所有task執行完畢(或者任一task執行完畢)後,開始執行後續操作

task.WhenAll(Task[] tasks) 表示所有的task都執行完畢後再去執行後續的操作, task.WhenAny(Task[] tasks) 表示任一task執行完畢後就開始執行後續操作

static void Main(string[] args)
        {
            ThreadblockThree();
            Console.WriteLine("主線程執行完畢!");
            Console.WriteLine("主線程ID:"+ Thread.CurrentThread.ManagedThreadId);
            Console.ReadKey();
        }


       private static void ThreadblockThree()
        {
            Task task1 = new Task(() =>
            {
                Thread.Sleep(500);
                Console.WriteLine("線程1執行完畢!");
            });
            task1.Start();
            Task task2 = new Task(() =>
            {
                Thread.Sleep(1000);
                Console.WriteLine("線程2執行完畢!");
            });
            task2.Start();
            //task1,task2執行完了後執行後續操作
            Task.WhenAll(task1, task2).ContinueWith((Task t) =>
            {
                Thread.Sleep(100);
                Console.WriteLine("執行後續操作完畢!");
            });
            //等同于
            //Task.Factory.ContinueWhenAll(new Task[] { task1, task2 }, (Task[] t) =>
            // {
            //   Thread.Sleep(100);
            //  Console.WriteLine("執行後續操作");
            //});

        }      
1.異步

08.

Task的任務取消(CancellationTokenSource)

private static void CancelTask()
        {
            CancellationTokenSource source=new CancellationTokenSource();
            int index = 0;
            Thread thread1=new Thread(() =>
            {
                while (source.IsCancellationRequested==false )
                {
                    Thread.Sleep(500);
                    Console.WriteLine($"第{++index}次執行");
                }
            });
            thread1.Start();
             //source.CancelAfter(5000)  實作5秒後自動取消任務
            //source.CancelAfter(3000);
            Thread.Sleep(3000);
            // source.Cancel()方法請求取消任務,IsCancellationRequested會變成true
            //設定一個狀态,設定該對象一個熟悉為true而已,也就是設定cts.IsCancellationRequested為ture。   
            //是以他根本沒有真正的去取消線程的執行,隻是設定一個狀态而已。
            source.Cancel();
            Console.WriteLine(source.IsCancellationRequested);

        }      
1.異步

09.source.Token.Register(Action action) 注冊取消任務觸發的回調函數,即任務被取消時注冊的action會被執行

// source.Token.Register(Action action) 注冊取消任務觸發的回調函數
       // 即任務被取消時注冊的action會被執行
       private static void CancelTaskTwo()
       {
            CancellationTokenSource source=new CancellationTokenSource();
            //注冊任務取消的事件
            source.Token.Register(() =>
            {
                //第5次執行在取消回調後列印,這是因為
                //執行取消的時候第5次任務已經通過了while()判斷,任務已經執行中了
                Console.WriteLine("任務取消後的回調!");
            });
            int index = 0;

            Task task=new Task(() =>
            {
                while (!source.IsCancellationRequested)
                {
                    Thread.Sleep(1000);
                    Console.WriteLine($"第{++index}次執行,線程運作中...");
                }
            });
            task.Start();
            source.CancelAfter(5000);//延時取消
        }      
1.異步