C#Task和async/await使用

一:什么是异步

当一个方法被调用时立即返回,并获取一个线程执行该方法内部的业务,调用者不用等待该方法执行完毕,我们称这个方法为异步方法。

  异步的好处在于非阻塞(调用线程不会暂停执行去等待子线程完成),因此我们把一些不需要立即使用结果、较耗时的任务设为异步执行,可以提高程序的运行效率。net4.0在ThreadPool的基础上推出了Task类,微软极力推荐使用Task来执行异步任务,现在C#类库中的异步方法基本都用到了Task;net5.0推出了async/await,让异步编程更为方便。本篇主要介绍Task、async/await相关的内容。

二:Task介绍

ThreadPool不能控制线程池中线程的执行顺序,也不能获取线程池内线程取消/异常/完成的通知。net4.0在ThreadPool的基础上推出了Task,Task拥有线程池的优点,同时也解决了使用线程池不易控制的弊端。

1、Task创建与运行

 1.1 创建task三种方式

Task task = new Task(() =>
            {
                Console.WriteLine("第一个任务!");
            });
            task.Start();
            Task.Factory.StartNew(() =>
            {
                Console.WriteLine("第二个任务");
            });
            Task.Run(() =>
            {
                Console.WriteLine("第三个任务");
            });
            Console.WriteLine("执行主线程!");

 运行结果:

C#Task和async/await使用

 

 

1.2 带返回值的Task

var task = new Task<string>(() =>
            {
                return "第一个任务";
            });
            task.Start();
            var task2 = Task<string>.Factory.StartNew(() =>
              {
                  return "第二个任务";
              }).Result;
            var task3 = Task<string>.Run<string>(() =>
              {
                  return "第三个任务";
              }).Result;
            Console.WriteLine(task.Result);
            Console.WriteLine(task2);
            Console.WriteLine(task3);
            Console.WriteLine("执行主线程!");
            Console.ReadKey();

运行结果:

C#Task和async/await使用

 

 

 1.3 Task同步执行

Task task = new Task(() =>
{
Console.WriteLine("第一个任务!");
});
task.RunSynchronously();

2、Task的阻塞方法(Wait/WaitAll/WaitAny)

task.Wait()、task2.Wait()和Task.WaitAll(task,task2)意义相同

Task.WaitAny(task,task2)执行完任何一个即可执行下面代码

Task task = new Task(() =>
            {
                Console.WriteLine("第一个任务!");
            });
            task.Start();
            Task task2 = new Task(() =>
            {
                Console.WriteLine("第二个任务!");
            });
            task2.Start();
            //task.Wait();
            //task2.Wait();
            Task.WaitAny(task,task2);
            //Task.WaitAll(task, task2);

 3 Task的延续操作(WhenAny/WhenAll/ContinueWith)

WhenAll等待所有任务完成执行延续的操作
WhenAny等待某个任务完成执行延续的操作

ContinueWith延续执行
Task task = new Task(() =>
            {
                Console.WriteLine("第一个任务!");
            });
            task.Start();
            Task task2 = new Task(() =>
            {
                Console.WriteLine("第二个任务!");
            });
            task2.Start();
            Task.WhenAny(task, task2).ContinueWith((t) =>
            {
                Console.WriteLine("延续后执行!");
            });
            //Task.WhenAll(task, task2).ContinueWith((t) =>
            //{
            //    Console.WriteLine("延续后执行!");
            //});
            Console.WriteLine("执行主线程!");
            Console.ReadKey();

3、Task的任务取消(CancellationTokenSource)

 

CancellationTokenSource source = new CancellationTokenSource();
            //注册任务取消的事件
            source.Token.Register(() =>
            {
                Console.WriteLine("任务被取消后执行!");
            });

            int index = 0;
            //开启一个task执行任务
            Task task1 = new Task(() =>
            {
                while (!source.IsCancellationRequested)
                {
                    Thread.Sleep(1000);
                    Console.WriteLine($"第{++index}次执行,线程运行中...");
                }
            });
            task1.Start();
            //延时取消,效果等同于Thread.Sleep(5000);source.Cancel();
            source.CancelAfter(5000);
            Console.ReadKey();

 

三:异步方法

static void Main(string[] args)
{
    var name = GetNameAsync().GetAwaiter().GetResult();
            SaveInfoAsync().GetAwaiter().GetResult();
            Console.WriteLine(name);
}
/// <summary>
/// 异步带返回值
/// </summary>
/// <returns></returns>   
static async Task<string> GetNameAsync()
{
            return "wuzhd";
}
/// <summary>
/// 异步无返回值
/// </summary>
/// <returns></returns>
static async Task SaveInfoAsync()
{

}

 

C#Task和async/await使用

上一篇:c# Http请求下载二进制流文件


下一篇:RESTful API风格