前言

TAP是基于Task的异步编程设计模式,

异步编程

  • async : async关键字修饰的方法都会被视为异步方法,编译器会为方法生成一个对应的状态机
  • await : await关键字后面代表可等待方法,编译器会转化成TaskAwait去处理异步

async修饰符代表了这个方法是异步方法,编译器会生成状态机。

1
2
3
4
5
6
7
8
9
10
//
public async Task MethodAsync()
{
//do some thing

//可等待方法,clr会挂起,等异步方法执行完才会执行剩下的逻辑
await Method1Async();

//do some thing
}

异步取消

采用CancellationToken来管理整个取消逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
CancellationTokenSource source = new CancellationTokenSource();
CancellationToken token = source.Token;

var result await MethodAsync(token);

//外部取消
source.Cancel();

public async Task MethodAsync(CancellationToken token)
{
//内部取消
source.Cancel();

}

TAP转换APM

采用TaskCompletionSource

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static Task<int> ReadTask(this Stream stream, byte[] buffer, int offset, int count, object state)
{
var tcs = new TaskCompletionSource<int>();
stream.BeginRead(buffer, offset, count, ar =>
{
try
{
tcs.SetResult(stream.EndRead(ar));
}
catch (Exception exc)
{
tcs.SetException(exc);
}
}, state);
return tcs.Task;
}

官方封装了工具类TaskToApm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//Task转APM密封类
internal sealed class TaskAsyncResult:IAsyncResult{...}

//Task转成APM对应的Begin方法
public static IAsyncResult Begin(Task task, AsyncCallback? callback, object? state) =>
new TaskAsyncResult(task, state, callback);

public static TResult End<TResult>(IAsyncResult asyncResult)
{
if (GetTask(asyncResult) is Task<TResult> task)
{
return task.GetAwaiter().GetResult();
}

ThrowArgumentException(asyncResult);
return default!; // unreachable
}

//转换后的Begin方法使用
public void BeginMethod(AsyncCallback callback,object? )
{
TaskToApm.Begin(MethodAsync(),callback,null);
}

小结

TAP已经让异步编程无感了,就像正常的方法一样,不用再关心如何去处理结果。