は、ここで私が何をしたいの易しく書き直さダウンバージョンです: 非同期に非同期デリゲートを呼び出しますか?
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()
)を呼び出すためにどのように動作するかを見ることができます。
非同期関数()を呼びたいときに問題が発生します。私が戻った結果はタイプ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 = await GetResultsAsync(n => IncAsync(n).Result、numbers);' –
'async void'は使用しないでください。これはイベントハンドラ専用です。 'async void'メソッドを待つことはできません –
また' await Task.WhenAll(tasks);タスクを返します。選択(t => t.Result); '?どうして?すべてのタスクに戻り値の型がある場合、 'WhenAll'は結果の配列を返します。コードをクリーンアップすると、 'int [] results = Await Task.WhenAll(tasks);' –