异步 async & await

Posted 仅供记录,日常灌水

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了异步 async & await相关的知识,希望对你有一定的参考价值。

1 什么是异步

异步的另外一种含义是计算机多线程的异步处理。与同步处理相对,异步处理不用阻塞当前线程来等待处理完成,而是允许后续操作,直至其它线程将处理完成,并回调通知此线程。

 

2 异步场景

  • l  不涉及共享资源,或对共享资源只读,即非互斥操作
  • l  没有时序上的严格关系
  • l  不需要原子操作,或可以通过其他方式控制原子性
  • l  常用于IO操作等耗时操作,因为比较影响客户体验和使用性能
  • l  不影响主线程逻辑

 

3 异步编写 C#

Async  await关键字

 Async method

三种返回类型

–      void (public async void InvokeAsync();) (应仅用于事件处理程序)

–      Task (pubic async Task InvokeAsync();)

–      Task<T> (public async Task<string> InvokeAsync();)

await 不会开启新的线程,当前线程会一直往下走直到遇到真正的Async方法(比如说HttpClient.GetStringAsync),这个方法的内部会用Task.Run或者Task.Factory.StartNew 去开启线程。也就是如果方法不是.NET为我们提供的Async方法,我们需要自己创建Task,才会真正的去创建线程

static void Main(string[] args)
        {
            Console.WriteLine("Main Thread Id: {0}\\r\\n", Thread.CurrentThread.ManagedThreadId);
            Test();
            Console.ReadLine();
        }

        static async Task Test()
        {
            Console.WriteLine("Before calling GetName, Thread Id: {0}\\r\\n", Thread.CurrentThread.ManagedThreadId);
            var name = GetName();   //我们这里没有用 await,所以下面的代码可以继续执行
                                    // 但是如果上面是 await GetName(),下面的代码就不会立即执行,输出结果就不一样了。
            Console.WriteLine("End calling GetName.\\r\\n");
            Console.WriteLine("Get result from GetName: {0}", await name);
        }

        static async Task<string> GetName()
        {
            // 这里还是主线程
            Console.WriteLine("Before calling Task.Run, current thread Id is: {0}", Thread.CurrentThread.ManagedThreadId);
            return await Task.Run(() =>
            {
                Thread.Sleep(1000);
                Console.WriteLine("\'GetName\' Thread Id: {0}", Thread.CurrentThread.ManagedThreadId);
                return "Jesse";
            });
        }

 

 

  1. 进入主线程开始执行
  2. 调用async方法,返回一个Task,注意这个时候另外一个线程已经开始运行,也就是GetName里面的 Task 已经开始工作了
  3. 主线程继续往下走
  4. 第3步和第4步是同时进行的,主线程并没有挂起等待
  5. 如果另一个线程已经执行完毕,name.IsCompleted=true,主线程仍然不用挂起,直接拿结果就可以了。如果另一个线程还同有执行完毕, name.IsCompleted=false,那么主线程会挂起等待,直到返回结果为止。

使用注意:

  • 异步代码使用 Task<T> 和 Task,它们是对后台所完成的工作进行建模的构造。
  • async 关键字将方法转换为异步方法,这使你能在其正文中使用 await 关键字。
  • 应用 await 关键字后,它将挂起调用方法,并将控制权返还给调用方,直到等待的任务完成。
  • 仅允许在异步方法中使用 await。
  • async 方法需在其主体中具有 await 关键字,否则它们将永不暂停!
  • 应将“Async”作为后缀添加到所编写的每个异步方法名称中。

 

  • await 语句 (await Task)
Task task = client.SendMailAsync(mailMessage);

await task;

 

await 表达式

Task<byte[]> task = webClient.DownloadDataTaskAsync(uri);

byte[] result = await task;

OR

byte[] result = await webClient.DownloadDataTaskAsync(uri);

 

 

部分内容引用来自

http://www.cnblogs.com/jesse2013/p/async-and-await.html

以上是关于异步 async & await的主要内容,如果未能解决你的问题,请参考以下文章

如何使用Async&Await将同步代码转换为异步编程

kotlin的suspend对比csharp的async&await

异步编程(async&await)

异步 async & await

JavaScript的ES6中async&&await的简单使用以及介绍

async & await 异步编程的一点巧方法