码迷,mamicode.com
首页 > 其他好文 > 详细

异步(1) async & await

时间:2017-12-30 23:35:36      阅读:161      评论:0      收藏:0      [点我收藏+]

标签:任务   complete   mail   div   adl   logs   uri   阻塞   and   

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

异步(1) async & await

标签:任务   complete   mail   div   adl   logs   uri   阻塞   and   

原文地址:https://www.cnblogs.com/dreamtaker/p/8126223.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!