早上无意中看到了async和await关键字,花了十几分钟看了一下msdn,大概明白了是什么一个东西,和大家分享一下。
await关键字的中文是期待的意思。在我们编程中想表达“我待会期待这里会有一个值,但我不是现在就要,我先去做其他事情,你完成的时候告诉我”。其实异步模式非常符合现实中场景,现实生活中还真的很少东西是同步的。等车的时候没事干可以拿手机出来玩一下,首发下邮件,而不是直愣愣的干在那里等着车过来。
话说回来,在C# 5中借助await可以更好的辅助我们进行异步编程模式的开发,通过改变执行流程,使得异步执行看起来更像同步执行。
一个async方法里通常包含一个或多个的对应的await操作符,但如果没有 await表达式也不会导致编译错误。但如果调用一个async方 法,却不使用await关键字来标记一个挂起点的话,程序将会忽略async关键字并以同步的方式执行。编译器会对类似的问题发出警告。
我直接拿msdn里的代码和图来举例吧。
public partial class MainWindow : Window { private async void StartButton_Click(object sender, RoutedEventArgs e) { int contentLength = await AccessTheWebAsync(); resultsTextBox.Text += String.Format("\r\nLength of the downloaded string: {0}.\r\n", contentLength); } async Task<int> AccessTheWebAsync() { HttpClient client = new HttpClient(); Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com"); DoIndependentWork(); string urlContents = await getStringTask; return urlContents.Length; } void DoIndependentWork() { resultsTextBox.Text += "Working . . . . . . .\r\n"; } }
可以从图中看出,和正常的执行流程是不一样的,我们甚至还会回到“看似已经执行完的方法中”,接着await下面执行
但其实这也不难理解,如果你用过yield return的话。可以看做执行到await的时候(箭头第6步),方法就返回了。等await后面的动作执行完以后我们再回来继续执行下面的步骤。
返回到方法的调用方。
finally 块不会运行。
但天有不测风云,壮士有可能一去不复返,改一下StartButton_Click代码,看下面的这个情况
1 private void StartButton_Click(object sender, RoutedEventArgs e) 2 { 3 int contentLength = AccessTheWebAsync().Result; 4 5 resultsTextBox.Text += 6 String.Format("\r\nLength of the downloaded string: {0}.\r\n", contentLength); 7 }
我们调用了task的Result,这个属性内部会调用await的方法,也就是会阻塞线程,也就是说线程执行到第3行的时候,就会被阻塞了(阻塞线程是罪大恶极的事情,要牢记在心)。一直等待AccessTheWebAsync()方法完成。
但是AccessTheWebAsync()能完成吗?答案是不能!因为AccessTheWebAsync方法需要依赖这个已经被阻塞的线程回去完成。好吧,一个互相等待的死锁出现了。
你妈妈喊你回家吃饭,快点来接着执行await下面的代码
我靠,我被Result定住了,没办法回去了。