一、相关介绍
.NetFramework3.0时代实现,C#中多线程、异步编程最佳实践,特点:
1、所有的Task操作的线程来自线程池,避免了频繁的线程创建及销毁
2、含有丰富的Api,能满足我们在开发过程中的各种场景(异步、多线程的执行顺序控制)
Task的执行底层还是thread执行
 
二、Task的创建方式
1、Task.Start
            //1、start——无返回值的方法,无参数(Action)、有一个参数Action<object?>
            //1.1带参数的——public Task(Action<object?> action, object? state);
            Action<Object?> action = objects =>
            {
                NoReturn(objects?.ToString());
            };
            var task1 = new Task(action, new Person());
            task1.Start();
            ////1.2不带参数的——public Task(Action action);
            Action action1 = NoParameterNoReturn;
            var task2 = new Task(action1);
            task2.Start();

 

2、Task.Run

相关重载

//public static Task Run(Action action, CancellationToken cancellationToken);
//public static Task<TResult> Run<TResult>(Func<TResult> function);
//Task<string>.Run(NoParameterReturn);
//public static Task<TResult> Run<TResult>(Func<TResult> function, CancellationToken cancellationToken);
//public static Task Run(Func<Task?> function);暂时没确定应用场景

public static class TaskRunSummary
    {
        public static async void RunTaskSummary()
        {
            //Task.Run()    Action  Lambda
            Task t1 = Task.Run(() => { Debug.WriteLine("Task.Run()    Action  Lambda"); });
            await t1;

            //Task.Run()    Func<Task>  Lambda  Async
            Task t2 = Task.Run(async () => { Debug.WriteLine("Task.Run()    Func<Task>  Lambda  Async"); });
            await t2;

            //Task.Run()    Func<Task>  Method  Async
            Task t3 = Task.Run(MethodAsync);
            await t3;

            //Task.Run<TResult>()    Func<TResult>  Lambda
            Task<string> t4 = Task.Run<string>(() => { Debug.WriteLine("Task.Run<TResult>()    Func<TResult>  Lambda"); return "Task.Run<TResult>()    Func<TResult>  Lambda Return Value"; });
            Console.WriteLine(await t4);

            //Task.Run<TResult>()    Func<Task<TResult>>  Lambda  Async
            Task<string> t5 = Task.Run<string>(async () => { Debug.WriteLine("Task.Run<TResult>()    Func<Task<TResult>>  Lambda  Async"); return "Task.Run<TResult>()    Func<Task<TResult>>  Lambda Async  Return Value"; });
            Console.WriteLine(await t5);

            //Task.Run<TResult>()    Func<Task<TResult>>  Method  Async
            Task<string> t6 = Task.Run<string>(new Func<Task<string>>(ParameteredMethodAsync));
            Console.WriteLine(await t6);
        }

        public static async Task MethodAsync()
        {
            Debug.WriteLine("Task.Run()    Func<Task>  Method  Async");
        }

        public static async Task<string> ParameteredMethodAsync()
        {
            Debug.WriteLine("Task.Run<TResult>()    Func<Task<TResult>>  Method  Async");
            return "Task.Run<TResult>()    Func<Task<TResult>>  Method Async  Return Value";
        }
    }

 

3、Task.Factory.StartNew——支持Action、Action<T>、Func<T>等参数

            Task.Factory.StartNew(NoParameterNoReturn);
            //3.1TaskFactory执行,和3差不多3是创建一个匿名TaskFactory去执行
            TaskFactory taskFactory1 = new TaskFactory();
            taskFactory1.StartNew(NoParameterNoReturn);
public static void NoParameterNoReturn()
        {
            
            Debug.WriteLine("无参数无返回值方法");
        }

 

 三、Task的相关属性及方法

Task.Delay

1.Task.Delay实质是创建一个任务,再任务中开启一个定时间,然后延时指定的时间
2.Task.Delay不和await一起使用情况,当代码遇到Task.Delay一句时,创建了了一个新的任务去执行延时去了,当前代码继续往下执行
3.Task.Delay和await一起使用,当代码遇到await Task.Delay时候,当前线程要等该行代码执行完成后,再继续执行后面的代码

Delay与Thread.sleep的区别

Thread.Sleep——这是暂停执行的经典方式。此方法将暂停当前线程,直到经过给定的时间,在此期间当前线程无响应

Task.Delay——任务延迟的作用方式与线程截然不同。延迟将创建一个任务,该任务将在延迟一段时间后完成。任务延迟不会阻塞调用线程,因此调用线程将保持响应。

ContinueWith——

ContinueWith(Action<Task>)创建一个在目标 Task 完成时异步执行的延续任务。常和Task.Delay一起使用用来做延迟动作

        public static async Task UseDelayWithAwait()
        {
            Debug.WriteLine($"使用Await的线程id:{Thread.CurrentThread.ManagedThreadId}执行开始》》");
            Stopwatch sw = Stopwatch.StartNew();
            await Task.Delay(1000);
            sw.Stop();
            Debug.WriteLine($"使用Await的线程id:{Thread.CurrentThread.ManagedThreadId}执行完毕,耗时{sw.ElapsedMilliseconds}毫秒");
        }
        public static void  UseDelayWithNoAwait()
        {
            Debug.WriteLine($"不使用Await的线程id:{Thread.CurrentThread.ManagedThreadId}执行开始》》");
            Stopwatch sw = Stopwatch.StartNew();
            Task.Delay(1000);
            sw.Stop();
            Debug.WriteLine($"不使用Await的线程id:{Thread.CurrentThread.ManagedThreadId}执行完毕,耗时{sw.ElapsedMilliseconds}毫秒");
        }
     public static async Task ContinueWithMethod()
    {
     Stopwatch sw = Stopwatch.StartNew();
     Debug.WriteLine($"当前线程id:{Thread.CurrentThread.ManagedThreadId}");
     await Task.Delay(3000).ContinueWith(t =>
     {
       Debug.WriteLine($"ContinueWith创建的Task线程id:{Thread.CurrentThread.ManagedThreadId}");
     });
     sw.Stop();
     Debug.WriteLine($"延迟三秒后的Task执行完毕,耗时{sw.ElapsedMilliseconds}毫秒");
    }

//执行结果

            //Task.Delay总结
            {
                //1、当前cpu执行线程遇到await Task.Delay时,会等待但他等待时会执行其他任务(不阻塞),在等待完成时由本执行cpu或其他执行cpu继续执行,所以await delay前后的代码可能不是一个cpu执行线程在执行,所以会出现下面的结果
                Task.Run(() => TaskDelaySummary.UseDelayWithAwait());
                //结果打印1:
                //使用Await的线程id:4执行开始》》
                //使用Await的线程id:5执行完毕,耗时1011毫秒
                //结果打印2:
                //使用Await的线程id:7执行开始》》
                //使用Await的线程id:7执行完毕,耗时1007毫秒

                //2、在不和await调用时,当执行cpu遇到Task.Delay时,不会等待,直接继续执行,所以前后的执行线程id是一致的
                Task.Run(() => TaskDelaySummary.UseDelayWithNoAwait());
                //结果打印:
                //不使用Await的线程id:4执行开始》》
                //不使用Await的线程id:4执行完毕,耗时0毫秒

Task.Run(async () => { await TaskContinueWithSummary.ContinueWithMethod(); }); //结果打印: //当前线程id:4 //ContinueWith创建的Task线程id:5 //延迟三秒后的Task执行完毕,耗时3015毫秒 }