如何添加一个异步"等待"到的AddRange select语句?

问题描述:

我有这样的功能:

public async Task<SomeViewModel> SampleFunction()
{
    var data = service.GetData();
    var myList = new List<SomeViewModel>();

    myList.AddRange(data.select(x => new SomeViewModel
    {
        Id = x.Id,
        DateCreated = x.DateCreated,
        Data = await service.GetSomeDataById(x.Id)
    }

    return myList;
}

我的伺机不工作,因为它只能用于在方法或lambda标有异步改性剂。我在哪里可以放在异步使用此功能?

My await isn't working as it can only be used in a method or lambda marked with the async modifier. Where do I place the async with this function?

您只能使用等待内的异步方法/委托。在这种情况下,你必须标记拉姆达EX pression为异步

You can only use await inside an async method/delegate. In this case you must mark that lambda expression as async.

别急,还有更精彩的......

But wait, there's more...

选择从pre - 异步时代,所以它不处理异步 lambda表达式(在你的情况下,它会返回的IEnumerable&LT;任务&LT; SomeViewModel&GT;&GT; 而不是的IEnumerable&LT; SomeViewModel&GT; 这是你真正需要的)

Select is from the pre-async era and so it doesn't handle async lambdas (in your case it would return IEnumerable<Task<SomeViewModel>> instead of IEnumerable<SomeViewModel> which is what you actually need).

不过,您可以添加该功能你自己($ P pferably $作为一个扩展的方法),但你需要考虑你是否希望等待移动到前每个项目下一个(sequentialy)或者等待所有项目一起末(兼)。

You can however add that functionality yourself (preferably as an extension method), but you need to consider whether you wish to await each item before moving on to the next (sequentialy) or await all items together at the end (concurrently).

static async Task<TResult[]> SelectAsync<TItem, TResult>(this IEnumerable<TItem> enumerable, Func<TItem, Task<TResult>> selector)
{
    var results = new List<TResult>();
    foreach (var item in enumerable)
    {
        results.Add(await selector(item));
    }
    return results.ToArray();
}

并行异步

static Task<TResult[]> SelectAsync<TItem, TResult>(this IEnumerable<TItem> enumerable, Func<TItem, Task<TResult>> selector)
{
    return Task.WhenAll(enumerable.Select(selector));
}

用法

public Task<SomeViewModel[]> SampleFunction()
{
    return service.GetData().SelectAsync(async x => new SomeViewModel
    {
        Id = x.Id,
        DateCreated = x.DateCreated,
        Data = await service.GetSomeDataById(x.Id)
    }
}