Вот упрощенная вниз версия того, что я хочу сделать:Асинхронный вызов асинхронного делегата?
private static int Inc(int input)
{
return input + 1;
}
private static async Task<int> IncAsync(int input)
{
await Task.Delay(200);
return input + 1;
}
private static async Task<IEnumerable<TResult>> GetResultsAsync<TInput, TResult>(Func<TInput, TResult> func, IEnumerable<TInput> values)
{
var tasks = values.Select(value => Task.Run(() => func(value)))
.ToList();
await Task.WhenAll(tasks);
return tasks.Select(t => t.Result);
}
public async void TestAsyncStuff()
{
var numbers = new[] { 1, 2, 3, 4 };
var resultSync = await GetResultsAsync(Inc, numbers); // returns IEnumerable<int>
Console.WriteLine(string.Join(",", resultSync.Select(n => $"{n}")));
// The next line is the important one:
var resultAsync = await GetResultsAsync(IncAsync, numbers); // returns IEnumerable<Task<int>>
}
Так в основном, GetResultsAsync()
предназначен для общего метода, который получит результаты функции для набора входных значений. В TestAsyncStuff()
вы можете увидеть, как это работает для вызова синхронной функции (Inc()
).
Проблема возникает, когда я хочу вызвать асинхронную функцию (IncAsync()
). Результат, который я возвращаю, имеет тип IEnumerable<Task<int>>
. Я мог бы сделать Task.WhenAll()
на этот результат, и это работает:
var tasksAsync = (await GetResultsAsync(IncAsync, numbers)).ToList();
await Task.WhenAll(tasksAsync);
var resultAsync = tasksAsync.Select(t => t.Result);
Console.WriteLine(string.Join(",", resultAsync.Select(n => $"{n}")));
Но я хотел бы, чтобы подтянуть код и сделать await
инлайн. Это должно выглядеть примерно так:
var resultAsync = await GetResultsAsync(async n => await IncAsync(n), numbers);
Но это также возвращает IEnumerable<Task<int>>
! Я мог бы сделать это:
var resultAsync = await GetResultsAsync(n => IncAsync(n).GetAwaiter().GetResult(), numbers);
И это работает ... но от того, что я видел, использование Task.GetAwaiter().GetResult()
или Task.Result
не рекомендуется.
Итак, каков правильный способ сделать это?
'var resultAsync = ожидание GetResultsAsync (n => IncAsync (n) .Result, numbers);'? –
Не используйте 'async void', это предназначено только для обработчиков событий. Вы не можете ждать метода «async void» –
Также «ждут Task.WhenAll (задачи); return tasks.Select (t => t.Result); '? Зачем? Если все задачи имеют тип возврата, 'WhenAll' возвращает массив результатов. Очищая код, вы должны иметь возможность писать 'int [] results = await Task.WhenAll (tasks);' –