[.Net] ลอง Share Pattern Parallel.ForEach ที่ผมใช้ครับ

จาก Blog ตอนที่แล้ว เรื่อง [.Net] มาทำให้ Parallel.ForEach Debug ง่ายกันเถอะ มาวันนี้ผมขอ Share Pattern ที่ได้ลองใช้ Parallel.ForEach เจ็บมาเยอะครับ เดี๋ยวผมลองแปะโครง Code แล้วมาอธิบายทีละจุดครับ ลองอ่านตาม Comment ได้ครับ

private DsetExpIVPDetailDTO ProcessDetail(IList pIVPDSList, IDictionary pMarketData)
{
    Object lockMe = new Object();

    //สร้าง List สำหรับเก็บผลลัพธ์ ระวีง List ไม่ Thread-safe ครับ
    IList DsetExpIVPDetailList = new List();
    //Thread มันทำงานแยกกัน เวลาดัก Exception ต้องแยกดักครับ 
    ConcurrentQueue exceptions = new ConcurrentQueue();
    //อันนี้มาจาก Blog ตอนที่แล้วครับ https://naiwaen.debuggingsoft.com/2016/09/net-parallel-foreach-debugging-trick/
    var parallelOptions = new ParallelOptions(); 
    #if DEBUG 
        parallelOptions.MaxDegreeOfParallelism = 1; 
    #endif
    //Parallel.ForEach
    Parallel.ForEach(pDsetExpProcess.IVPPreProcessDSList, parallelOptions, IVPDataSourceEntry =>
    {
        //พึงระวังไว้เสมอ Code ทุกอันมี Bug ดักด้วยครับ แบ่งกันทำ แต่ไม่มีคนจับ Bug 555
        try
        {
            #region Process Detail
            //ฺBusiness Process ตอนนี้ที่ผม คือ DataSet IVP ครับ

            //List ไม่ Thread-safe แต่ละ Thread ที่ทำงานมา เราต้อง Lock ให้ List มีคนเข้าถึงได้ที่ละอันครับ ไม่งั้นงง
            lock (lockMe)
            {
                DsetExpIVPDetailList.Add(DsetExpIVPDetailEntry);
            }
            #endregion Process Detail
        }
        catch (Exception e)
        {
            logger.Debug("Error Message : " + e.StackTrace);
            //โยน Exception เข้าคิว
            exceptions.Enqueue(e);
        }
    });
    //แบ่งงานเสร็จ มาดูว่ามี Error ไหม ถ้ามีให้โยนออกมา
    if (exceptions.Count > 0) throw new AggregateException(exceptions);

    return DsetExpIVPDetailList;
}

จาก Comment ผมมีใช้คำสั่งหลายตัวเลย ได้แก่

  • ConcurrentQueue<Exception> เมื่องานแยกกันทำ เราต้องมีตัวจัดลำดับของ Error เก็บไว้ ถ้าไม่มี แล้วเกิดมีโยนออกมา ไม่มีใครรับ Exception มันก็จะบึ้มเงียบ หรือหาสาเหตุไม่ได้ครับ สำหรับผมในส่วนของ Catch ถ้ามี Exception มาก็จะ Enqueue ไว้ครับ
  • ParallelOptions ตาม Blog ตอนที่แล้ว เลยครับ ที่ผมสนใจตัว MaxDegreeOfParallelism ครับ
  • Lock - เนื่องจาก List ไม่เป็น Thread Safe ผมเลยต้อง Lock เพื่อให้ List ถูกเข้าถึงได้ 1 Thread เท่านั้นครับ

ลองนำไปปรับใช้กันดูได้นะครับ ^___^


Discover more from naiwaen@DebuggingSoft

Subscribe to get the latest posts sent to your email.