异步lambda:“任务被取消”

时间:2016-09-17 19:53:23

标签: c# asp.net asynchronous lambda async-await

这是工作流程:

  1. 对WebApi2端点的传入HTTP请求。
  2. 进行同步(例如非异步)调用以获取一些数据。
  3. 将数据库实体的响应映射到API模型。 一个。执行AutoMapper映射。 湾包括以下代码段(见下文)。 C。如果操作“快”,没问题。如果操作“慢”,则抛出“任务被取消”异常。
  4. 在映射操作很快的情况下,我很幸运。但是如果我添加Task.Delay(2000),那么我会得到有问题的异常。似乎ASP.NET没有“等待”我的异步lamba完成?

    这是映射表达式的主体:

    mapping.AfterMap(async (entity, model) => {
        var child = await _childRepo.Get(entity.ChildId);
        await Task.Delay(2000); // For testing, of course.
        if (child != null)
        {
            // Fill in some properties on model
        }
    });
    

    请注意,这是示例代码,我不打算在“真实生活”中进行映射期间进行额外的DB / repo调用。

1 个答案:

答案 0 :(得分:2)

AfterMap takes an Action,这是synchronous delegate, not an asynchronous delegate(正如我在博客中解释的那样)。因此,它与@ lambdas无法正常工作。

在这种情况下(因为委托返回@using(Html.BeginForm("Index", "Manage", FormMethod.Post, new { @class = "form-inline", Id = "ManageEmployeeForm" })) { @Html.AntiForgeryToken(); @Html.HiddenFor(m => m.ActionForm.From); @Html.HiddenFor(m => m.ActionForm.To); <div class="form-group"> @Html.LabelFor(m => m.ActionForm.UserId, new { @class = "sr-only" }); @Html.DropDownListFor(x => x.ActionForm.UserId, Model.Users, new { @class = "form-control" }); @Html.ValidationMessageFor(m => m.ActionForm.UserId); </div> .... ),编译器实际上将允许async lambda;但是,它将编译为void方法。 (编译器执行此操作以允许async事件处理程序)。正如我在关于异步最佳实践的MSDN文章中所描述的那样,您应该avoid async void

避免async void的一个原因是很难检测async方法何时完成。事实上,(除了WebForm生命周期事件),ASP.NET甚至都不会尝试这样做。