虽然在编写 WebAPI 时不直接支持取消,但 OWIN API 绝对支持。如果您使用的是 WebAPI 2.0,您将在 OWIN 之上运行,并且将能够使用 GetOwinContext() 扩展方法通过 Microsoft 包装器访问上下文。
使用通过OwinRequest 的CallCancelled 属性公开的CancellationToken 值很方便地传播取消。您可以将所有这些放在一起以在控制器方法中获取令牌:
public async Task Get()
{
var cancellation = Request.GetOwinContext().Request.CallCancelled;
await database.FooAsync(cancellation);
}
虽然这很丑。您必须在需要处理取消的每个方法中进行此调用,并且它不适用于 WebAPI 将为您提供此CancellationToken 的提议的未来。相反,如果我们能把它变成一个参数不是更好吗?
public async Task Get(CancellationToken cancellation)
{
await database.FooAsync(cancellation);
}
为此,您可以创建一个自定义参数绑定,从 OWIN 上下文中获取 CancellationToken:
public class OwinCancellationTokenBinding : HttpParameterBinding
{
public OwinCancellationTokenBinding(HttpParameterDescriptor parameter)
: base(parameter)
{
}
public override Task ExecuteBindingAsync(
ModelMetadataProvider metadataProvider,
HttpActionContext actionContext,
CancellationToken cancellationToken)
{
actionContext.ActionArguments[Descriptor.ParameterName]
= actionContext.Request.GetOwinContext().Request.CallCancelled;
return Task.FromResult<object>(null);
}
}
要使用它,您可以使用 HttpConfiguration 的 ParameterBindingRules 集合注册绑定:
config.ParameterBindingRules.Add(p
=> p.ParameterType == typeof(CancellationToken)
? new OwinCancellationTokenBinding (p)
: null);
此规则匹配CancellationToken 类型的任何参数。您可以在此处创建与您希望为其提供此值的参数匹配的任何规则。