【问题标题】:Adding items to an outer collection from within a ForEachAsync, implicity captured closure从 ForEachAsync 中将项目添加到外部集合,隐式捕获的闭包
【发布时间】:2016-12-30 23:06:23
【问题描述】:

首先,正如他们所说,我对异步操作有足够的了解是危险的。 Resharper 使用下面的代码向我发出警告,我在 ForEachAsync 处为“响应”对象隐式捕获了闭包。我理解它为什么警告我,但我不确定我的实现是否有什么特别的问题(顺便说一句,这确实有效),或者是否有更合适的方法从 ForEachAsync 中填充“订单”集合。

  public async Task<Response<IEnumerable<Order>>> HandleGetOrdersAsync(GetAllOrdersQuery query)
  {
     Expression<Func<Order, bool>> dateTimeFilter = order =>
        order.OrderTime >= query.StartDateTime &&
        order.OrderTime <= query.EndDateTime;

     Expression<Func<order, bool>> isActiveFilter = order =>
        !query.IsComplete ||
        order.OrderStatus == OrderStatusName.Complete;

     var items = _ctx.orders
        .Include(c => c.Customers)
        .Include(p => p.Payments)
        .Where(dateTimeFilter)
        .Where(isActiveFilter)
        .OrderBy(n => n.OrderNo)
        .Skip(query.PageSize * query.Page)
        .Take(query.PageSize)
        .Select(o => o);

     // ... items count to be performed here ...

     var response = new Response<IEnumerable<Order>>();
     var orders = new List<Order>();

     await items.ForEachAsync(i =>
     {
        var order = new Order
        {
           ResultNo = i.OrderNo,
           CustomerName = i.Customer.Name,
           PaymentType = i.Payment.Type
        };

        orders.Add(order);

     }).ContinueWith(t =>
     {
        response = new Response<IEnumerable<Order>>(orders);
     });

     return response;
  }

【问题讨论】:

  • 为什么你的代码中有ContinueWith?只需 await Task 并使用它解析的结果。

标签: c# async-await


【解决方案1】:

您的代码将如您所见,但委托将保持 orders 变量活动,因为它具有对它的引用,因此只要委托不是,您的类将无法被 GC 收集有资格进行垃圾收集。

 var orders = new List<Order>();

 await items.ForEachAsync(i =>
 {
    var order = new Order
    {
       ResultNo = i.OrderNo,
       CustomerName = i.Customer.Name,
       PaymentType = i.Payment.Type
    };

    orders.Add(order);

 }).ContinueWith(t =>
 {
    response = new Response<IEnumerable<Order>>(orders);
 });

如果 orders 是 int 等值类型呢?

在这种情况下它不适用,但是如果orders 是一个整数并且没有await 并且代码在捕获orders 变量的委托之后继续,并且您在委托之后修改变量,并且稍后调用委托(想想事件处理程序)它将使用修改后的副本。为什么?因为event虽然是整数,但是引用被捕获了。

我猜 Resharper 只是在警告您,您需要决定它是否会导致您的案件出现问题。它所能做的就是警告您,因为在某些情况下它可能会导致问题,而在其他情况下不会导致任何问题。

【讨论】:

    猜你喜欢
    • 2013-06-10
    • 1970-01-01
    • 2012-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-03
    • 2011-02-06
    • 1970-01-01
    相关资源
    最近更新 更多