2020年9月23日 星期三

多工作業(平行處理)注意事項

※使用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) =>
{
            ....
});

沒有留言:

input 連結 datalist 用程式控制彈出選項

範例: nextTick(() => document.querySelector('input').showPicker());  ※僅支援現代瀏覽器