1. 引入
同步,任务以固定的顺序执行。异步,任务不需要按照固定顺序执行。从.net4.5开始,异步主要通过Task实现。异步编程的核心是Task和Task<T>对象,用来模拟异步操作,并通过async和await关键字修饰。其中异步模型的操作,一般分为以下2种:
(1)对于I/O绑定的代码,await将在异步方法中返回一个Task或Task<T>;
(2)对于绑定CPU类的程序,await将在带有Task.Run()方法的后台线程上启动操作;
2. 异步编程的三种模式
这三种模式的实现,以"从指定的偏移量开始将指定数量的数据读入提供的缓存区"为例进行实现。
public class MyClass { public int Read(byte[] buffer, int offset, int count); }
该方法的TAP模式实现如下:
public class MyClass { public Task<int> ReadAsync(byte[] buffer, int offset, int count); }
EAP对应方法将公开一下类型和成员:
public class MyClass { public void ReadAsync(byte [] buffer, int offset, int count); public event ReadCompletedEventHandler ReadCompleted; }
APM模式下实现如下:
public class MyClass { public IAsyncResult BeginRead(byte [] buffer,int offset, int count,AsyncCallback callback, object state); public int EndRead(IAsyncResult asyncResult); }
3. 异步操作的实现
3.1 I/O绑定实例
场景描述: 点击按钮从web服务下载数据,但不能锁定UI线程。
private readonly HttpClient _httpClient=new HttpClient(); downloadButton.Click +=async (o,e)=> { //在web服务请求发生时间向UI提供控制 //UI线程自由地执行其他工作 var stringData = await _httpClient.GetStringAsync(URL); DoSomethingWithData(stringData); }
3.2 CPU绑定实例:执行游戏计算
场景描述:写一个手机端游戏,点击按钮对屏幕上许多敌人造成伤害,但执行损害计算的代价可能是昂贵的,并且在UI线程上执行计算时可能导致界面暂停。
解决该问题的最佳办法是开启一个用Task.Run工作的后台线程,用await等待返回结果。
private DamageResult CalculateDamageDone() { // Code omitted: // // Does an expensive calculation and returns // the result of that calculation. } calculateButton.Clicked += async (o, e) => { // This line will yield control to the UI while CalculateDamageDone() // performs its work. The UI thread is free to perform other work. var damageResult = await Task.Run(() => CalculateDamageDone()); DisplayDamage(damageResult); };
3.3 关键点
3.4 如何分辨是I/O绑定还是CPU绑定?
(1)如果代码需要“等待”,例如来自数据库的数据,则为I/O绑定;
(2)如果代码执行需要消耗大代价的计算,则为CPU绑定。
4. 总结
原文:https://www.cnblogs.com/mo-lu/p/11114671.html