諮詢區
-
Satish:
我建了一個 Console 程序想用異步的方式處理集合,我做了兩個版本。
-
使用 parallel 方式遍歷集合。
-
使用 async,await 遍歷集合。
測試下來,我發現 async/await
的執行方式是同步的,這就很尷尬了,我如何用 async/await
實現 parallel
的方式呢?這是我寫的測試代碼:
class Program
{
static void Main(string[] args)
{
var worker = new Worker();
worker.ParallelInit();
var t = worker.Init();
t.Wait();
Console.ReadKey();
}
}
public class Worker
{
public async Task<bool> Init()
{
var series = Enumerable.Range(1, 5).ToList();
foreach (var i in series)
{
Console.WriteLine("Starting Process {0}", i);
var result = await DoWorkAsync(i);
if (result)
{
Console.WriteLine("Ending Process {0}", i);
}
}
return true;
}
public async Task<bool> DoWorkAsync(int i)
{
Console.WriteLine("working..{0}", i);
await Task.Delay(1000);
return true;
}
public bool ParallelInit()
{
var series = Enumerable.Range(1, 5).ToList();
Parallel.ForEach(series, i =>
{
Console.WriteLine("Starting Process {0}", i);
DoWorkAsync(i);
Console.WriteLine("Ending Process {0}", i);
});
return true;
}
}
回答區
-
Tim S.:
你使用 await 的姿勢無形中就告訴 C# 你每loop一次都要await一下,這種方式肯定就串行了,你可以將需要並行迭代的 item 封裝到 Task.WhenAll
中,然後用 await 一次等待就可以了,參考如下代碼:
public async Task<bool> Init()
{
var series = Enumerable.Range(1, 5).ToList();
var tasks = new List<Task<Tuple<int, bool>>>();
foreach (var i in series)
{
Console.WriteLine("Starting Process {0}", i);
tasks.Add(DoWorkAsync(i));
}
foreach (var task in await Task.WhenAll(tasks))
{
if (task.Item2)
{
Console.WriteLine("Ending Process {0}", task.Item1);
}
}
return true;
}
public async Task<Tuple<int, bool>> DoWorkAsync(int i)
{
Console.WriteLine("working..{0}", i);
await Task.Delay(1000);
return Tuple.Create(i, true);
}
點評區
相信這幾年大家做的新項目都是滿屏的 await,async 了吧,異步的優點還是大大提高了驅動設備的利用率,不然也不會有各種導致堆碎片化的 Overlapped 🤣,異步也是一種串行,學會怎麼在異步串行中組合並行的方式,對開發來說很有用,學習了。
本文分享自微信公衆號 - 一線碼農聊技術(dotnetfly)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。