Как выполнить GroupBy по результату асинхронного метода Task <string>и получить группировку по строке в C #? - PullRequest
0 голосов
/ 13 мая 2019

У меня есть метод ниже (это метод расширения, но он не имеет отношения к этому вопросу), и я хотел бы использовать GroupBy для результатов метода.

class MyClass 
{
    public async Task<string> GetRank() 
    {
        return "X";
    }

    public async static Task Test()
    {
       List<MyClass> items = new List<MyClass>() { new MyClass() };
       var grouped = items.GroupBy(async _ => (await _.GetRank()));
    }
}

Тип grouped is IGrouping<Task<string>, MyClass>, однако мне нужно сгруппировать по фактическому ожидаемому результату асинхронного метода (строка).Несмотря на то, что я использую await и делаю лямбда-асинхронный вывод, я все равно получаю IGrouping<Task<string>, ..> вместо IGrouping<string, ...>

Как использовать GroupBy и group в результате асинхронного Task<string> метода и получить группировку по строке?

Ответы [ 2 ]

2 голосов
/ 13 мая 2019

Вы, вероятно, ищете await все ваши задачи * сначала 1003 *, затем группа

// projection to task 
var tasks = items.Select(y => AsyncMethod(y);

// Await them all
var results = await Task.WhenAll(tasks)

// group stuff
var groups = results.GroupBy(x => ...);

Полная демонстрация здесь

Примечание : у вас действительно не было тестируемого кода, поэтому я просто подключил что-то подобное

Обновление

причина, по которой ваш пример не работает

items.GroupBy(async _ => (await _.GetRank())) 

, заключается в том, что async лямбда на самом деле просто метод, который возвращает задачу, этопочему вы получаете IGrouping<Task<string>, MyClass>

Вам нужно подождать, пока все ваши задачи завершатся, прежде чем вы сможете подумать о том, чтобы что-то сделать с результатами задачи

Чтобы более подробно объяснить, что происходит, примитевзгляд на этот пример SharpLab

Ваш async лямбда в основном разрешает это

new Func<int, Task<string>>(<>c__DisplayClass1_.<M>b__0)
0 голосов
/ 13 мая 2019

Вот асинхронная версия GroupBy. Он ожидает задачу в результате keySelector и возвращает задачу, которую можно ожидать:

public static async Task<IEnumerable<IGrouping<TKey, TSource>>>
    GroupByAsync<TSource, TKey>(this IEnumerable<TSource> source,
    Func<TSource, Task<TKey>> keySelector)
{
    var tasks = source.Select(async item => (Key: await keySelector(item), Item: item));
    var entries = await Task.WhenAll(tasks);
    return entries.GroupBy(entry => entry.Key, entry => entry.Item);
}

Может использоваться следующим образом:

class MyClass
{
    public async Task<string> GetRank()
    {
        await Task.Delay(100);
        return "X";
    }

    public async static Task Test()
    {
        var items = new List<MyClass>() { new MyClass(), new MyClass() };
        var grouped = items.GroupByAsync(async _ => (await _.GetRank()));
        foreach (var grouping in await grouped)
        {
            Console.WriteLine($"Key: {grouping.Key}, Count: {grouping.Count()}");
        }
    }
}

Выход:

Ключ: X, Количество: 2

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...