美文网首页后端
asp.net core 中async/await 使用

asp.net core 中async/await 使用

作者: Daniel_adu | 来源:发表于2017-01-13 17:43 被阅读288次

    asp.net core 中async/await 使用

    async/await是用来进行异步调用的形式,内部其实还是采用线程池进行管理。
    我们从两方面来看其运行机制,运行流程和运行线程。

    单独的await

            public async Task<string> call()
            {
                Debug.WriteLine("----------->1");
                int s = await foo();
                Debug.WriteLine("----------->2");
                return "1";
            }
            public async Task<int> foo()
            {
                Debug.WriteLine("----------->3");
                await Task.Delay(500);
                Debug.WriteLine("----------->4");
                return 1;
            }
    
    

    运行结果:

    ----------->1
    ----------->3
    ----------->4
    ----------->2
    
    

    这个很好理解,先主线程运行,然后运行子线程foo()方法,线程等待foo方法运行完毕之后再继续往下运行。

    我们从线程的角度来看一下这里面的线程切换。
    Talk is cheap, show me the code

            public async Task<string> Get()
            {
                var info = string.Format("----------->1:{0}", Thread.CurrentThread.ManagedThreadId);
                var infoTask = await TaskCaller();
                var infoTaskFinished = string.Format("----------->2:{0}", Thread.CurrentThread.ManagedThreadId);
                return string.Format("{0},{1},{2}", info, infoTask, infoTaskFinished);
            }
    
            private async Task<string> TaskCaller()
            {
                await Task.Delay(500);
                return string.Format("----------->3:{0}", Thread.CurrentThread.ManagedThreadId);
            }
    
    

    结果是

    ----------->1:1
    ----------->3:4
    ----------->2:4
    
    

    冒号后面的是线程编号,一开始主线程为1,然后进入到子线程4,跳出来之后居然在线程4中执行!很神奇,异步线程接管了接下来的活!

    有人就要说了,这个await很同步获取result一样啊,看不出有什么异步的优势在里面,客官莫急,接下来慢慢看。

    分开的await

            public async Task<string> call()
            {
                Debug.WriteLine("----------->1");
                Task<int> infoTask = foo();
                Debug.WriteLine("----------->2");
                int s = await infoTask;
                Debug.WriteLine("----------->3");
                return "1";
            }
            public async Task<int> foo()
            {
                Debug.WriteLine("----------->4");
                await Task.Delay(500);
                Debug.WriteLine("----------->5");
                return 1;
            }
    
    

    定义异步方法foo,然后在call方法中调用,与第一个例子不一样的是这个例子foo()不立马使用await,而是运行一段之后再使用await,结果输出如下:

    ----------->1
    ----------->4
    ----------->2
    ----------->5
    ----------->3
    
    

    看看这个神奇的线程输出吧。
    Talk is cheap, show me the code

            public async Task<string> Get()
            {
                var info = string.Format("----------->1:{0}", Thread.CurrentThread.ManagedThreadId);
                Task<string> task = TaskCaller();
                var infoTaskRunning = string.Format("----------->2:{0}", Thread.CurrentThread.ManagedThreadId);
                var infoTask = await task;
                var infoTaskFinished = string.Format("----------->3:{0}", Thread.CurrentThread.ManagedThreadId);
                return string.Format("{0},{1},{2},{3}", info, infoTask,infoTaskRunning, infoTaskFinished);
            }
    
            private async Task<string> TaskCaller()
            {
                await Task.Delay(500);
                return string.Format("----------->4:{0}", Thread.CurrentThread.ManagedThreadId);
            }
    
    

    猜猜结果是什么。

    ----------->1:1
    ----------->4:4
    ----------->2:1
    ----------->3:4
    
    

    一开始运行在主线程,后来跳到async方法中执行在线程4中,在没有使用await时,主线程并没有停下来,还是按照自己的路往下走,直到async使用了await方法,下面的代码也是交给了子线程。
    至于为什么交给了子线程处理,有一篇文章说是await前后的代码被分成块,将await的task交给线程池,线程池执行完毕之后进行moveNext方法,继续执行await之后的代码。
    有兴趣的可以看看这篇文章
    async和await刨根问底

    当有多个async方法在主程序中被调用

    执行的流程就不说了,大家都清楚,主要来看看执行的线程
    Talk is cheap, show me the code

            public async Task<string> Get()
            {
                var info = string.Format("----------->1:{0}", Thread.CurrentThread.ManagedThreadId);
                Task<string> task1 = TaskCaller1();
                Task<string> task2 = TaskCaller2();
                var infoTaskRunning = string.Format("----------->2:{0}", Thread.CurrentThread.ManagedThreadId);
                var infoTask1 = await task1;
                var infoTaskFinished1 = string.Format("----------->3:{0}", Thread.CurrentThread.ManagedThreadId);
    
                var infoTask2 = await task2;
       
                var infoTaskFinished2 = string.Format("----------->4:{0}", Thread.CurrentThread.ManagedThreadId);
    
                return string.Format("{0},{1},{2},{3},{4},{5}", info, infoTask1, infoTask2,infoTaskRunning, infoTaskFinished1, infoTaskFinished1);
            }
    
            private async Task<string> TaskCaller1()
            {
                await Task.Delay(500);
                return string.Format("----------->5:{0}", Thread.CurrentThread.ManagedThreadId);
            }
    
           private async Task<string> TaskCaller2()
            {
                await Task.Delay(500);
                return string.Format("----------->6:{0}", Thread.CurrentThread.ManagedThreadId);
            }
    
    

    结果如下:

    ----------->1:4
    ----------->5:3
    ----------->6:12
    ----------->2:4
    ----------->3:3
    ----------->4:3
    
    

    有没有有个数字很奇怪,对,就是最后的3,前面讲过async会接过线程来自己操作下面的代码,第一个异步方法确实是这样做了,使得第一个await async之后在线程3上面操作,
    而第二个await之后却还是在线程3上面操作,这不免有些让人疑惑,还是建议去看上面推荐的async和await刨根问底

    相关文章

      网友评论

        本文标题:asp.net core 中async/await 使用

        本文链接:https://www.haomeiwen.com/subject/rymhbttx.html