异步初探
前言:由于没有在生产环境,以及很少写异步代码,经验较少。因此本篇博客只是通过一些实例来初探异步。其中大量的示例来自,Tomas Petricek的博文《Async in C# and F#: Asynchronous gotchas in C#》
抛出问题什么是异步,下面通过一个简单的示例来解释,分为C#版本与F#版本,首先为C#版本
1 static async Task WorkThenWait() 2 { 3 Thread.Sleep(1000); 4 Console.WriteLine("work"); 5 await Task.Delay(1000); 6 } 7 8 void Demo() 9 { 10 var child = WorkThenWait(); 11 Console.WriteLine("started"); 12 child.Wait(); 13 Console.WriteLine("completed"); 14 }
然而这段代码,并没有按照预期的,打印“started”, "work",和"completed",而是,seleep 1000毫秒,打印work接着打印started,然后等待WorkThenWait异步操作也就是Task.Delay(1000)结束,然后打印"completed"。至于为什么是这样,是因为,在C#中,async修饰的异步方法,内部是同步执行的,直到遇到await表达式,此时将WorkThenWait()挂起,直到await的任务完成,同时控制返回到WorkThenWait的调用方法中,也就是Demo中。所以整个流程就是:
调用Demo--->创建child对象,WorkThenWait()方法执行--->WorkThenWait()内部同步执行第3行和第4行,到第5行挂起,同时把控制交回到Demo方法-->执行Demo方法第11行-->Demo第12行等待异步方法完成-->Demo第13行-->结束。
到这里,这个例子似乎还是不能很直观的解释异步是什么,下面通过F#的例子来解释
1 let workThenWait = async { 2 Thread.Sleep(1000) 3 printfn "work done" 4 do! Async.Sleep(1000) 5 } 6 7 let demo = 8 let work = workThenWait |> Async.StartAsTask 9 printfn "started" 10 work.Wait() 11 printfn "completed"
没错,调用demo,一切都是按照想象中的顺序执行的,创建work任务,启动work任务,控制权交回demo,打印"started",等待work任务,执行work中的代码,回到demo,打印completed,结束。F#中async包裹的函数体都是异步执行的。通过这两个实例,基本上已经很明确的解释了什么是异步了,接下来就是大量的细节。在Tomas的博客中还有几个实例,都是通过C#和F#的异步编程中的一些不同的地方。本文尚未完结,慢慢补充。