首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在SelectMany中使用异步lambda?

如何在SelectMany中使用异步lambda?
EN

Stack Overflow用户
提问于 2015-11-03 09:32:58
回答 4查看 16.9K关注 0票数 40

在尝试在async中使用IEnumerable.SelectMany lambda时,我得到了以下错误

代码语言:javascript
运行
复制
var result = myEnumerable.SelectMany(async (c) => await Functions.GetDataAsync(c.Id));

不能从用法中推断方法“IEnumerable System.Linq.Enumerable.SelectMany(this IEnumerable,Func>)”的类型参数。尝试显式指定类型参数。

其中GetDataAsync被定义为:

代码语言:javascript
运行
复制
public interface IFunctions {
    Task<IEnumerable<DataItem>> GetDataAsync(string itemId);
}

public class Functions : IFunctions {
    public async Task<IEnumerable<DataItem>> GetDataAsync(string itemId) {
        // return await httpCall();
    }
}

我猜是因为我的GetDataAsync方法实际上返回一个Task<IEnumerable<T>>。但是为什么Select要工作,当然它应该抛出同样的错误?

代码语言:javascript
运行
复制
var result = myEnumerable.Select(async (c) => await Functions.GetDataAsync(c.Id));

有办法绕过这件事吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2015-11-03 09:48:47

异步lambda表达式不能转换为简单的Func<TSource, TResult>

因此,选择多个不能使用。您可以在同步上下文中运行:

代码语言:javascript
运行
复制
myEnumerable.Select(c => Functions.GetDataAsync(c.Id)).SelectMany(task => task.Result);

代码语言:javascript
运行
复制
List<DataItem> result = new List<DataItem>();

foreach (var ele in myEnumerable)
{
    result.AddRange(await Functions.GetDataAsyncDo(ele.Id));
}

你既不能使用yield return,也不能使用它--它是设计出来的。f.e.:

代码语言:javascript
运行
复制
public async Task<IEnuemrable<DataItem>> Do() 
{
    ...
    foreach (var ele in await Functions.GetDataAsyncDo(ele.Id)) 
    {
        yield return ele; // compile time error, async method 
                          // cannot be used with yield return
    }

}
票数 19
EN

Stack Overflow用户

发布于 2016-03-08 18:17:10

这是一个扩展:

代码语言:javascript
运行
复制
public static async Task<IEnumerable<T1>> SelectManyAsync<T, T1>(this IEnumerable<T> enumeration, Func<T, Task<IEnumerable<T1>>> func)
{
    return (await Task.WhenAll(enumeration.Select(func))).SelectMany(s => s);
}

它允许您运行:

代码语言:javascript
运行
复制
var result = await myEnumerable.SelectManyAsync(c => Functions.GetDataAsync(c.Id));

说明:您有一个任务列表,每个任务都返回Task<IEnumerable<T>>。因此,您需要解雇他们,然后等待所有,然后通过SelectMany压扁结果。

票数 61
EN

Stack Overflow用户

发布于 2017-10-19 07:45:14

Select之所以工作,是因为它将返回一个IEnumerable<Task<T>>,然后可以与Task.WhenAll一起等待。

因此,解决这个问题的一个简单方法是:

代码语言:javascript
运行
复制
IEnumerable<Task<IEnumerable<T>>> tasks = source.Select(GetNestedEnumerableTask);
IEnumerable<T>[] nestedResults = await Task.WhenAll(tasks);
IEnumerable<T> results = nestedResults.SelectMany(nr => nr);
票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33495617

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档