Ben*_*Fox 3 .net asynchronous task async-await c#-4.0
我目前正在实现一个System.Web.Http.IActionFilter调用内部服务来确定当前请求是否可以继续.我遇到的问题是返回一个Task<T1>基于a封装的逻辑Task<T2>.
一个例子可能有帮助.
内部服务API使用Tasks实现.使用.NET 4.5的异步/等待逻辑是微不足道的:
public async Task<HttpResponseMessage> ExecuteActionFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
{
UserAuthenticationResult authResult = await HitInternalServiceAsync();
if (!authResult.IsAuthenticated)
{
throw new HttpResponseException("User is not authenticated", HttpStatusCode.Unauthorized);
}
return await continuation();
}
Run Code Online (Sandbox Code Playgroud)
但是,使用.NET 4.0中的旧Task API会更加困难;
public Task<HttpResponseMessage> ExecuteActionFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
{
return HitInternalServiceAsync()
.ContinueWith(t1 => {
UserAuthenticationResult authResult = t1.Result;
if (!authResult.IsAuthenticated)
{
throw new HttpResponseException("User is not authenticated", HttpStatusCode.Unauthorized);
}
//Hack hack - this blocks the thread until the task retuned by continuation() completes
return continuation().Result;
});
}
Run Code Online (Sandbox Code Playgroud)
当身份验证检查成功时,困难的部分就会出现 - 然后我想等待continuation函数返回的任务.
使用.NET 4.0看起来我在等待continuation()任务完成时显式阻塞,而不是指示任务API continuation()在我的任务完成时自动继续执行任务.
给定一个足够复杂的内部服务API,我可以很容易地看到等待其他任务的任务数量快速增加.
编辑:看起来上面的4.0代码也不可行 - 因为延续lambda不在ASP.NET线程上下文服务中执行,如HttpContext.Current不可用.更好的实施将是......
public Task<HttpResponseMessage> ExecuteActionFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
{
Task<UserAuthenticationResult> authResultTask = HitInternalServiceAsync();
var authResult = authResultTask.Result;
if (!authResult.IsAuthenticated)
{
throw new HttpResponseException("User is not authenticated", HttpStatusCode.Unauthorized);
}
return continuation();
}
Run Code Online (Sandbox Code Playgroud)
你的问题是,如果你不使用Result,ContinueWith()将返回Task<Task<HttpResponseMessage>>而不是Task<HttpResponseMessage>你需要的.
幸运的是,已经存在一种将any转换Task<Task<T>>为Task<T>:的方法Unwrap().所以只是return continuation();从ContinueWith()lambda然后调用Unwrap()结果.
如果希望继续在ASP.NET上下文中执行,则可以使用TaskScheduler.FromCurrentSynchronizationContext().
| 归档时间: |
|
| 查看次数: |
1659 次 |
| 最近记录: |