【问题标题】:select from linq statement with await从带有等待的 linq 语句中选择
【发布时间】:2019-11-07 00:28:11
【问题描述】:

这个好像应该很简单,我有如下代码

var additionalInformation=   response.AdditionalInformation.Select( async x =>  new AdditionalInformationItem
                {
                    StatementCode = x?.StatementCode?.Value,
                    LimitDateTime = x?.LimitDateTime?.Item?.Value,
                    StatementTypeCode = x?.StatementTypeCode?.Value,
                    StatementDescription = x?.StatementDescription?.Value,
                    AdditionalInformationResult = await BuildAdditionalInformationPointers(x)


                }).ToList();

我想要实现的是附加信息的类型为

List<AdditionalInformationItem>

,我得到的是List&lt;Task&lt;AdditionalInformationItem&gt;&gt;

谁能帮助我正确地重新表述我的陈述?

【问题讨论】:

  • 为什么是异步 lambda?有什么具体原因吗?如果你想要并行 Linq,那么可能使用相同的
  • @Rahul,因为它正在调用异步函数 BuildAdditionalInformationPointers()

标签: c# linq .net-core async-await


【解决方案1】:

您需要使用await Task.WhenAll(additionalInformation) 解包任务,然后使用additionalInformation[0].Result 访问实际结果。

所以是这样的:

var additionalInformation=   response.AdditionalInformation.Select( async x =>  new AdditionalInformationItem
                {
                    StatementCode = x?.StatementCode?.Value,
                    LimitDateTime = x?.LimitDateTime?.Item?.Value,
                    StatementTypeCode = x?.StatementTypeCode?.Value,
                    StatementDescription = x?.StatementDescription?.Value,
                    AdditionalInformationResult = await BuildAdditionalInformationPointers(x)


                });

await Task.WhenAll(additionalInformation);
//This will iterate the results so may not be the most efficient method if you have a lot of results
List<AdditionalInformationItem> unwrapped = additionalInformation.Select(s => s.Result).ToList();

【讨论】:

    【解决方案2】:

    实际上没有办法在简单的 lambda 表达式中做到这一点。异步 lambda 表达式将始终返回 Task&lt;T&gt;。所以你可以快速而肮脏地在Task上调用.Result(不要这样做!除非你像Liam的answer一样先等待),或者只是初始化一个新列表并在foreach循环中添加项目:

    var additionalInformation = new List<AdditionalInformationItem>();
    foreach (var x in response.AdditionalInformation)
    {
        var item = new AdditionalInformationItem
            {
                StatementCode = x?.StatementCode?.Value,
                LimitDateTime = x?.LimitDateTime?.Item?.Value,
                StatementTypeCode = x?.StatementTypeCode?.Value,
                StatementDescription = x?.StatementDescription?.Value,
                AdditionalInformationResult = await BuildAdditionalInformationPointers(x)
            };
    
        additionalInformation.Add(item);
    }
    

    【讨论】:

    • 如果你已经等待异步调用,访问.Result 是完全可以的。唯一不好的想法是,如果您没有等待异步调用完成,那么这可能会导致死锁
    • @Liam 你是对的,正如你的回答中所阐明的那样。
    【解决方案3】:

    await Task.WhenAll 将自动解包任务,并将结果交给您一个数组。

    AdditionalInformationItem[] additionalInformation = await Task.WhenAll(
        response.AdditionalInformation.Select(async x => new AdditionalInformationItem
        {
            StatementCode = x?.StatementCode?.Value,
            LimitDateTime = x?.LimitDateTime?.Item?.Value,
            StatementTypeCode = x?.StatementTypeCode?.Value,
            StatementDescription = x?.StatementDescription?.Value,
            AdditionalInformationResult = await BuildAdditionalInformationPointers(x)
        });
    );
    

    【讨论】:

      猜你喜欢
      • 2020-07-30
      • 1970-01-01
      • 1970-01-01
      • 2019-09-17
      • 1970-01-01
      • 2017-08-03
      • 2012-01-12
      • 1970-01-01
      • 2013-12-27
      相关资源
      最近更新 更多