這裏是什麼,我想要做一個簡單化下來的版本:異步調用異步委託?
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 = await GetResultsAsync(n => IncAsync(n).Result,numbers);'? –
不要使用'async void',它只能用於事件處理程序。你不能等待'async void'方法 –
也'等待Task.WhenAll(任務);返回任務。選擇(t => t.Result);'?爲什麼?如果所有任務都有返回類型,則'WhenAll'返回結果數組。通過清理代碼,你應該可以編寫'int [] results = await Task.WhenAll(tasks);' –