深入理解async和await(一)

C#中的await和async,一直都不是非常明白,其里头的具体机制如何?让我们先看一下下面的程序。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Net;
using System.Threading;
using System.Threading.Tasks;

namespace MyTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Main before:" + Thread.CurrentThread.ManagedThreadId);
            Test();
            Console.WriteLine("Main end:" + Thread.CurrentThread.ManagedThreadId);

            Console.ReadKey();
        }

        static async Task Test()
        {
            Console.WriteLine("test before:" + Thread.CurrentThread.ManagedThreadId);
            await getName();
            Console.WriteLine("test end:" + Thread.CurrentThread.ManagedThreadId);
        }

        static async Task<string> getName()
        {
            Console.WriteLine("name before:" + Thread.CurrentThread.ManagedThreadId);

            await Task.Delay(1000);
            Console.WriteLine("name end:" + Thread.CurrentThread.ManagedThreadId);
            return await Task<string>.Run(() => {
                Console.WriteLine("task before:" + Thread.CurrentThread.ManagedThreadId);
                return "irisloveleo";
            });
        }
    }
}

上面的程序输入什么呢?想想,然后看下面的答案。

为什么会这样呢?让我们顺着这个答案反推出程序的执行过程。

1、开始进入main程序,当前的线程id为9

2、进入test函数,输出test before的线程id为9,表明此刻还没有产生新的线程,仍然顺序执行。

3、进入getName函数,输出name before的线程id为9,一直到此,都没有产生新的线程

4、下一步输出为Main end: 9,表明9线程(主线程)已经从getName函数退回到Test函数,但是Test函数在等待getName函数执行完毕,因此主线程继续退回到Main函数执行。

5、一秒之后,输出name end的线程为11,表明,从await Task.delay开始,新产生了一个线程

6、输出task before的线程id为12,表明此时有产生了一个新的线程

7、输出test end的线程id为12,表明利用的是getName中最后产生的那个线程,而本身不产生线程。


综上,可得出几个结论:

1、await并不产生新的线程,只有遇到真正的async方法,这个方法的内部会用Task.Run或者Task.Factory.StartNew 去开启线程

2、执行await后面语句的线程是async方法内产生的线程

3、Delay内部会产生一个新的线程用来控制延时,因此不会阻塞当前线程


0 条评论

    发表评论

    电子邮件地址不会被公开。 必填项已用 * 标注