再探async/await

c# 5.0 的时候就已经有了async/await语法,当时也没深入研究,看这字面意思就是异步等待,估计就是异步调用是等待其返回吧,事实也是那么回事,只是微软做的比较高级些,高级在哪?我们来看下下面的代码。

        static void Main(string[] args)
        {
            Console.WriteLine("Start");
            Console.WriteLine("Current Thread Id :{0}", Thread.CurrentThread.ManagedThreadId);
            Task.Delay(1000).Wait();
            Console.WriteLine("End");
            Console.WriteLine("Current Thread Id :{0}", Thread.CurrentThread.ManagedThreadId);
            Console.ReadKey();
        }

输出结果

 

这是传统的异步等待的写法,阻塞了主线程等待异步线程执行完返回,然后继续执行下面代码。

下面改用新的语法async/await会怎样呢?

        static async Task Main(string[] args)
        {
            Console.WriteLine("Start");
            Console.WriteLine("Current Thread Id :{0}", Thread.CurrentThread.ManagedThreadId);
            await Task.Delay(1000);
            Console.WriteLine("End");
            Console.WriteLine("Current Thread Id :{0}", Thread.CurrentThread.ManagedThreadId);
            Console.ReadKey();
        }

c# 7.1 已经支持程序入口函数Main方法使用async语法了,不过需要你手工改下语言版本,否则会报错。

输出结果

看出区别了吗?await后面的代码是在异步线程里执行的,主线程并没有阻塞等待。await后面的代码怎么就跑到别的线程里去执行了呢?我猜想微软大概是这么干的,把传统的写法改成下面这样是不是清楚很多:

        static void Main(string[] args)
        {
            Console.WriteLine("Start");
            Console.WriteLine("Current Thread Id :{0}", Thread.CurrentThread.ManagedThreadId);
            Task.Delay(1000).ContinueWith((t) =>
            {
                Console.WriteLine("End");
                Console.WriteLine("Current Thread Id :{0}", Thread.CurrentThread.ManagedThreadId);
                Console.ReadKey();
            }).Wait();
        }

但是末尾一定要跟一个Wait()否则主线程结束了,程序就退出了,可这样还是会阻塞主线程啊,这就是它async/await高级的地方了,抱歉,水平有限,鬼知道他做了什么?要知道main函数直到c# 7.1 才允许添加async修饰符,而且还不能写成async void只能写成async Task,这说明其中一定做了什么处理,望知道的大神不吝赐教。

那么await后面的事情都交给别人干了,主线程干嘛去了?好像碰到await他就休息去了,身为主线程你这样偷懒不好吧?虽然这样可以防止因为主线程阻塞而造成winform界面卡死,但这样也会让开发者更容易犯错,比如这样时

        [ThreadStatic]
        static string tss;
        static async Task Main(string[] args)
        {
            tss = "tssssssss";
            Console.WriteLine("Start");
            Console.WriteLine("Current Thread Id :{0}", Thread.CurrentThread.ManagedThreadId);
            Console.WriteLine(tss);
            await Task.Delay(1000);
            Console.WriteLine("End");
            Console.WriteLine("Current Thread Id :{0}", Thread.CurrentThread.ManagedThreadId);
            Console.WriteLine(tss);
            Console.ReadKey();
        }

await后的tss输出是空,知道了await前后的代码不在同一个线程里,一切就都好解释了,开发时得多留个心眼。

猜你喜欢

转载自www.cnblogs.com/tigeer/p/9560697.html