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

2020年9月21日 星期一

使用 epplus 加入圖表

以折線圖為例
var chart = sheet.Drawings.AddChart("圖表1", eChartType.Line);
var series= (ExcelLineChartSerie)chart.Series.Add(sheet.Cells[2,2,100,2], sheet.Cells[2,1,100,1]);
series.HeaderAddress = sheet.Cells[1, 2];
            

Entity Framework 建立新物件並儲存後馬上取得關聯資料

使用 CreateProxy 建立物件,不要直接 new var newmodel = _contextXXX.CreateProxy<yyy>(); ... _contextXXX.yyy.Add(newmodel); await _contextXXX.SaveC...