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

aync await 进一步探索

时间:2017-05-12 23:09:27      阅读:221      评论:0      收藏:0      [点我收藏+]

标签:中文   oid   imp   bsp   bgp   back   readline   异步调用   block   

aync await 进一步探索

首先来个例子

class Program
{
static int index = 1;
static void Log(string str)
{
Console.WriteLine((index++) + ". " + str + ". ThreadId:" + Thread.CurrentThread.ManagedThreadId);
}

        static void Main(string[] args)
        {
            //解决.net core控制台输出中文乱码的代码
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            //async 不能用于Main方法,所以在这里单独使用一个方法来调用,各位可以试试,编译不过,但VS就是不会告诉你错误在哪里
            ExcuteAsync(); 
            Console.ReadLine();
        }

        static async void ExcuteAsync() {
            Log("异步方法调用前");
            var ret = AsyncMethod();
            Log("异步方法调用后");
            Log(await ret);
            Log("异步方法使用await后");
        }

        static async Task<string> AsyncMethod() {
            Log("异步方法开始");
            var task = Task.Run<string>(() =>
            {
                Log("异步方法内部开始");
                Thread.Sleep(3000);
                Log("异步方法内部结束");
                return "来自异步方法内部的结果";
            });
            Log("异步方法结束");
            var ret = await task;
            Log("异步方法await结束");
            return ret;
        }
    }

控制台输出结果

1. 异步方法调用前. ThreadId:1
2. 异步方法开始. ThreadId:1
3. 异步方法结束. ThreadId:1
4. 异步方法内部开始. ThreadId:3
5. 异步方法调用后. ThreadId:1
6. 异步方法内部结束. ThreadId:3
7. 异步方法await结束. ThreadId:3
8. 来自异步方法内部的结果. ThreadId:3
9. 异步方法使用await后. ThreadId:3

分析

为了描述更方便,为每条输出都添加了序号。 为了更清晰的知道每一步的执行顺序以及所在的线程,均添加了ThreadId

  1. 第1条输出,主线程,没有什么特别的。
  2. 第2条输出,主线程,说明:调用异步方法本身并不会另起一个线程,如果这里面没有await的话,调用这个方法和调用普通方法没有任何区别。
  3. 第3条输出,主线程,说明:执行异步方法后主线程并没有被挂起,而是直接继续往下走。
  4. 第4条输出,线程3(代表子线程,不一定每次都是3),代码显示的要起用一个新线程,没有什么特别的。
  5. 第5条输出,主线程,和第3条一样,主线程继续往下走,只是代码在不同的方法里而已。
  6. 第6条输出,线程3,内部执行结束,没什么特别。
  7. 第7条输出,线程3,说明:这里有一个不同的地方,使用了await,可见,这里是子线程的延续
  8. 第8-9条输出,线程3,和第7条一样,延续了子线程。

变种

我们把ExcuteAsync方法里的await ret,改成ret.Result看看效果

1. 异步方法调用前. ThreadId:1
2. 异步方法开始. ThreadId:1
3. 异步方法结束. ThreadId:1
4. 异步方法内部开始. ThreadId:3
5. 异步方法调用后. ThreadId:1
6. 异步方法内部结束. ThreadId:3
7. 异步方法await结束. ThreadId:3
8. 来自异步方法内部的结果. ThreadId:1
9. 异步方法使用await后. ThreadId:1

第8-9条输出线程变了,可见是主线程被挂起了,等待子线程结束后继续往下执行。那么如果在AsyncMethod里也使用Result,效果又是什么样的?

我们把AsyncMethod方法里的await task改成task.Result,看输出结果

1. 异步方法调用前. ThreadId:1
2. 异步方法开始. ThreadId:1
3. 异步方法结束. ThreadId:1
4. 异步方法内部开始. ThreadId:3
5. 异步方法内部结束. ThreadId:3
6. 异步方法await结束. ThreadId:1
7. 异步方法调用后. ThreadId:1
8. 来自异步方法内部的结果. ThreadId:1
9. 异步方法使用await后. ThreadId:1

现在只有Task内部的输出是在子线程了。可见,使用Result的话会失去异步的效果,换句话说,使用Result就不再是异步调用了

 

附:文笔不好,只能用习惯的代码来描述,希望能给读者带来帮助。

?

aync await 进一步探索

标签:中文   oid   imp   bsp   bgp   back   readline   异步调用   block   

原文地址:http://www.cnblogs.com/rainhat/p/6847459.html

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