iT邦幫忙

0

Parallel.ForEach問題請教

  • 分享至 

  • xImage

最近想調整一段迴圈的程式
想到並行這做法
剛好有幾個問題想請教一下

以下是我的程式碼


var sBachSQL = new ConcurrentBag<資料庫連接相關CLASS>();

 try{
        Count = 0;
        SqlString = "";
        string[] lines = File.ReadAllLines(Path);

        if (lines != null && lines.Count() > 0)
        {
            Parallel.ForEach(lines, (item, loopState) =>
            {
                string data = item.ToString();
                try
                {
                   //解析並回傳更新的SQL語法
                   SqlString = RerurnSqlString(data);
                }
                catch (Exception exc)
                {
                                
                }
             if (SqlString.Trim() != "")
             {                               
                 sBachSQL.Add(SqlString);                               
                 Count++;
             }
              //每1000筆執行一次交易
             if ((Count == 1000))
             {
                 ExecuteTransaction(SqlString);
                 Count = 0;
                 SqlString = "";
                 sBachSQL = new ConcurrentBag<資料庫連接相關CLASS>();                           
              }
             });
       }

    }  

功能大概是我會讀取一個TXT檔,裡面可能會有上萬筆資料,讀取後
解析某個欄位並回傳SQL更新語法然後每1000筆進行一次交易
目前的問題是我寫LOG記錄我的COUNT數時我發現他不一定會呈現

0、1、2、3、4、5

有可能會呈現

0、1、1、2、4、5

或是別的可能性

我能請問是為什麼嗎?

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

0
Yue
iT邦新手 5 級 ‧ 2023-09-12 15:41:55

這是多執行緒取值的問題,Parallel.ForEach 也是一種多執行緒,如果需要修改相同的值需要使用lock
實際上完成的需求是甚麼我不太清楚, 你可以查一下Parallel.ForEach 跟 lock 的使用
如:https://dotblogs.com.tw/JesperLai/2018/04/06/010817

看更多先前的回應...收起先前的回應...
tenno081 iT邦研究生 4 級 ‧ 2023-09-12 15:46:13 檢舉

我想再請問,執行完後看一下資料庫發現有的資料沒更新到有可能也是這原因嗎?

Yue iT邦新手 5 級 ‧ 2023-09-12 15:58:02 檢舉

應該是相同原因, 你的 sBachSQL 這個變數也在多執行緒裡面被修改到.
另外,在執行緒中計數感覺不太保險.因為用lock雖然可以確定參數一次只有一個執行緒取得,但是無法確定取得的順序.
事先切割好陣列在進行多執行緒執行可能會比較好.
比如 1500 筆資料, 先切分 1000 + 500 在執行動作, 這樣就不用在裡面計數.

你指定Count為1000才執行交易,若你的總行數為3999
即是跑到最後一行 Count為999就結束了,那麼最後999比是否就沒有成功交易?你似乎沒有做最後未滿1千筆時的判定..

加上你用Parallel,Count沒有鎖定的狀態下,你甚至估不到最後有多少筆沒送...

這是我的猜測~

tenno081 iT邦研究生 4 級 ‧ 2023-09-12 16:09:29 檢舉

Yue感謝,這個想法我倒是沒想過,假設我有4000筆資料我有辦法分組成4個1000筆?計數那個只是我想觀察

tenno081 iT邦研究生 4 級 ‧ 2023-09-12 16:10:49 檢舉

緯大啊緯大人未滿1000筆的交易我有做,只是不是寫在Parallel裡。我這隻程式原本只是普通的迴圈,基於好奇我把它改成Parallel看看

噗 那我誤會了
/images/emoticon/emoticon01.gif

tenno081 iT邦研究生 4 級 ‧ 2023-09-12 16:19:46 檢舉

沒關係,分組的我倒是做好了,沒想到還有這種做法,哈哈,我看看後面怎麼弄~

Yue iT邦新手 5 級 ‧ 2023-09-13 10:53:07 檢舉

另外, 你也可以參考
https://dotblogs.com.tw/supershowwei/2016/12/09/221622
使用SqlBulkCopy 批次 Insert的方式,將工作丟給資料庫去執行分類
這樣你也不用自己分資料跟執行緒

我要發表回答

立即登入回答