※使用epplus,不要在task 中取得sheet,必須先取得後放入變數,在task 中存取該變數(pck.Workbook.Worksheets[i] 非安全執行緒)
List<ExcelWorksheet> sheets = new List<ExcelWorksheet>();
using (ExcelPackage pck = new ExcelPackage(new System.IO.FileInfo(excel_template), true)) {
pck.Workbook.Worksheets.ForEach(a => sheets.Add(a));
Parallel.For(1, 7,
i => {
var sheet = sheets.ElementAt(i-1);
※ 在多工中 epplus 使用 insertrow 會造成不定時出現錯誤訊息 xxx updatecrossreference xxx
※多個task 不要放在 List 中,要改用 ConcurrentBag 存放(代表安全執行緒的未排序物件集合),避免出現錯誤訊息:...集合已修改...
ConcurrentBag<Task> tasks = new ConcurrentBag<Task>();
tasks.Add(Task.Run(() => {...}));
tasks.Add(Task.Run(() => {...}));
Task.WaitAll(tasks.ToArray());
※entity framework 非安全執行緒,關聯資料無法在其他執行緒中取得,多工作業中需另外重新取得資料,且同一個db無法跨執行緒共用,會引發未預期錯誤
※多工作業中若會連線資料庫,要限制同時執行的工作數量,避免造成資料庫可用連線耗盡
using (var db = new ERPEntities())
{
var 訂單ids=db.訂單.Where(a=>a.日期==今天).Select(a=>a.id).ToList();
Parallel.ForEach(訂單ids,new ParallelOptions { MaxDegreeOfParallelism = 8 }, (訂單id) =>
{
using (var db = new ERPEntities())
{
var 訂單 = db.訂單.Single(a => a.id == 訂單id);
※DataTable 非安全執行緒,可以在多工作業查詢資料但不能異動資料
Parallel.ForEach 非同步版用法 (.Net 6 以上)
await Parallel.ForEachAsync(products, new ParallelOptions { MaxDegreeOfParallelism = 5 }, async (product, token) =>
{
....
});