.net - 合并不同类型的 .NET 4.0 任务/延续

标签 .net c#-4.0 asynchronous task async-await

我目前正在实现 System.Web.Http.IActionFilter它调用内部服务来确定当前请求是否可以继续。我遇到的问题是返回 Task<T1>基于由 Task<T2> 封装的一段逻辑.

一个例子可能会有所帮助。

内部服务 API 是使用 Tasks 实现的。使用 .NET 4.5 的 async/await 的逻辑很简单:

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();
}

但是在 .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;
            });
}

当身份验证检查成功时,困难的部分就来了——然后我想等待延续函数返回的任务。

使用 .NET 4.0 看起来我在等待 continuation() 时已明确阻止任务来完成,而不是指示任务 API 自动继续 continuation() 我的任务完成后的任务。

问题:这是在 .NET 4.0 中实现此行为的唯一方法吗?

给定一个足够复杂的内部服务 API,我可以很容易地看到等待其他任务的任务数量迅速增加。

编辑: 看起来上面的 4.0 代码也不可行 - 因为延续 lambda 不会在 HttpContext.Current 等 ASP.NET 线程上下文服务中执行不可用。更好的实现是......

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();
}

最佳答案

你的问题是,如果你不使用 Result , ContinueWith()将返回 Task<Task<HttpResponseMessage>>而不是 Task<HttpResponseMessage>你需要。

幸运的是,已经有一种方法可以转换任何 Task<Task<T>>Task<T> : Unwrap() .所以只需return continuation();来自 ContinueWith() lambda 然后调用 Unwrap()关于结果。

如果您希望继续在 ASP.NET 上下文中执行,您可以使用 TaskScheduler.FromCurrentSynchronizationContext() .

关于.net - 合并不同类型的 .NET 4.0 任务/延续,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10424392/

相关文章:

asp.net - 无法连接到多维数据集

wpf - 将相同类型的 View 模型列表绑定(bind)到 Caliburn.Micro 中的选项卡控件

c# - 在 .Net 2.0 项目中创建扩展方法,使用 C# 4.0 进行编译

javascript - 函数中的服务器变量

javascript - 如何正确编写异步加载函数的代码

c# - 如何使用带有 clickonce 的文本文件并在更新时能够更新它?

.net - Powershell Get-SCVirtualDiskDrive 生成​​公共(public)语言规范 (CLR) 错误

ios - Objective-C 中的异步编程 : I feel like there is repetitive code here and I don't know what I can do about it

.net - 连接到.net路由器后面的计算机

.net - Crystal 报表 : How do I use verify database with updated . 网络对象?