前言 最近寫了三篇關於並行非同步的博客,因為我走了很多彎路。 並行執行非同步方法並接收返回值這個問題,stackoverflow上討論好幾年,.NET 6實現了Parallel.ForeachAsync。https://stackoverflow.com/questions/15136542/paral ...
前言
最近寫了三篇關於並行非同步的博客,因為我走了很多彎路。
並行執行非同步方法並接收返回值這個問題,stackoverflow上討論好幾年,.NET 6實現了Parallel.ForeachAsync。https://stackoverflow.com/questions/15136542/parallel-foreach-with-asynchronous-lambda
.NET 6 中的 API Parallel.ForEachAsync 在官方的博客中一直被忽略,但是我覺得這個 API 非常的實用!(這句話參考了博客:https://blog.csdn.net/sD7O95O/article/details/117914853)
要求
- 必須接收處理返回值
示例1
示例2
代碼說明
- 上述代碼我覺得非常優雅,java是無法優雅地寫出來的,會很難閱讀和維護。java19也許可以。
- 使用場景:普通的增刪改查功能估計是用不到,但我用到了。
- 上述代碼的並行度,可以根據es集群的性能和吞吐量以及具體需求,進行合理的調整。
可以複製的代碼
上述代碼是圖片不方便複製,可以複製的代碼在 探索:優雅地實現非同步方法的並行執行 文章的最後。
簡單的示例Demo代碼
private async void button4_Click(object sender, EventArgs e)
{
await Task.Run(async () =>
{
Log($"==== 並行非同步 開始,線程ID={Thread.CurrentThread.ManagedThreadId} ========================");
Stopwatch sw = Stopwatch.StartNew();
HttpClient httpClient = HttpClientFactory.GetClient();
var tasks = new Dictionary<string, Task<Dictionary<int, int>>>();
ConcurrentQueue<string> strs = new ConcurrentQueue<string>();
await Parallel.ForEachAsync(Enumerable.Range(0, m), new ParallelOptions() { MaxDegreeOfParallelism = 100 }, async (i, c) =>
{
int sum = 0;
await Parallel.ForEachAsync(Enumerable.Range(0, n), new ParallelOptions() { MaxDegreeOfParallelism = 30 }, async (j, c) =>
{
Dictionary<int, int> dict = await RequestAsync(_url, i);
if (dict.ContainsKey(j))
{
int num = dict[j];
Interlocked.Exchange(ref sum, sum + num);
strs.Enqueue($"{num}");
}
});
Log($"輸出:sum={sum}");
});
Log($"輸出:{string.Join(",", strs.ToArray())}");
sw.Stop();
Log($"==== 結束,線程ID={Thread.CurrentThread.ManagedThreadId},耗時:{sw.Elapsed.TotalSeconds:0.000}秒 ========================");
});
}
上述代碼說明
代碼中 Parallel.ForEachAsync(Enumerable.Range(0, m),... 代替了for迴圈。