iT邦幫忙

0

C# 多執行緒即時更新一個DataTable

  • 分享至 

  • xImage

各位大大好
如標題,我目前需要同時開多個執行緒跟設備抓值
然後再把抓到的值塞到同一個DataTable中
最後再把DataTable的東西即時show到DataGridView上

目前的做法是把DataTable加到DataGridView.DataSource中
再透過多執行緒更新各自對應欄位儲存格的值
來達到畫面即時更新的效果

但目前測試下來畫面不是很卡就是容易整個卡死
因此想問問各位大大
如果在需要即時更新DataGridView畫面的前提下
有什麼更好的做法嗎?

下面是執行緒裡面唯一有更新DataTable的地方

private void SetStatus()
{
    try
    {
        if (Form1.form1.InvokeRequired)
        {
            Form1.form1.Invoke(new Action(SetStatus), new object[] { });
        }
        else
        {
            if (bool_AutoRun)
            {
                // -------------------------------
                // 這邊跟DataTable無關就先刪掉了
                // -------------------------------
                MPU.dt_MainTable.Rows[int_ThreadNum + index]["Static"] = str_Data[index];

                Application.DoEvents();
            }
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
}
看更多先前的討論...收起先前的討論...
canrong iT邦新手 2 級 ‧ 2022-09-08 15:36:35 檢舉
單看文字敘述,猜測鎖沒有很好的釋放資源,沒有code只能觀落陰。
皓皓 iT邦新手 3 級 ‧ 2022-09-08 16:01:12 檢舉
canrong 大大你好,抱歉因為原本程式碼太龐大我不知何貼起,我剛剛有更新文章了,我把各個設備執行緒裡面更新DataTable的語法貼出來了,各個設備的執行緒在撈完設備的值後都會呼叫這個方法去更新DataTable
先請教你的資料庫的連接方式是什麼?OleDB?ADODB.net?NativeSQL?

每個連接預設最多只能有100個交易池,你確定跑多執行緒不會over?陷入連綿不絕的死結裡嗎?
canrong iT邦新手 2 級 ‧ 2022-09-08 16:13:06 檢舉
我建議使用timer去委派更新畫面,將更新資料的邏輯獨立出來背景作業。
canrong iT邦新手 2 級 ‧ 2022-09-08 16:17:58 檢舉
刷新畫面的頻率一定比設備更新數據的速度慢很多... 你這樣寫就是一直委派用使用者互動的form thread去更新數據並顯示 但你SetStatus方法會因為設備數據更新而一直進來
皓皓 iT邦新手 3 級 ‧ 2022-09-08 16:27:22 檢舉
japhenchen 大大你好,我是用微軟的SQL Server,但我這邊都還沒有連到資料庫,只是單純讀取本機txt設備清單,並在抓值後更新DataTable和更新DataGridView,是最後處理完SQL語法才會由主執行緒去回寫資料庫

canrong 大大也就是說我設備數據更新後先把值用變數存起來,再由form的timer把值接回來去做畫面更新對嗎?
canrong iT邦新手 2 級 ‧ 2022-09-08 16:41:35 檢舉
皓皓 基本上是這樣做,並且多執行續使用同方法更新共用容器,你還需要去處理併發問題。簡單做的話可以試試看分別把值存在不同變數,或者可以使用ConcurrentDictionary更新數據,timer呼叫SetStatus把值一次更新DataTable容器並顯示。
canrong iT邦新手 2 級 ‧ 2022-09-08 16:48:22 檢舉
你的問題可能還不需要用到鎖,但你可以參考看看Mutex類別。
皓皓 iT邦新手 3 級 ‧ 2022-09-08 16:56:27 檢舉
感謝 canrong 大大解答,我再來去看看ConcurrentDictionary和Mutex的官方文件,看可以怎麼使用
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

0
JamesDoge
iT邦高手 1 級 ‧ 2022-12-23 04:39:26

可以使用 Control.Invoke 方法來在執行緒中即時更新 DataTable,如果您希望在 DataTable 更新時立即刷新 DataGridView 畫面,您可以在更新完 DataTable 後使用 DataGridView.Refresh 方法來立即刷新畫面。

如下:

private void SetStatus()
{
    try
    {
        if (Form1.form1.InvokeRequired)
        {
            Form1.form1.Invoke(new Action(SetStatus), new object[] { });
        }
        else
        {
            if (bool_AutoRun)
            {
                // 更新 DataTable
                MPU.dt_MainTable.Rows[int_ThreadNum + index]["Static"] = str_Data[index];

                // 刷新 DataGridView 畫面
                dataGridView1.Refresh();
            }
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

你也可以使用 Control.BeginInvoke 方法:

private void SetStatus()
{
    try
    {
        if (Form1.form1.InvokeRequired)
        {
            IAsyncResult result = Form1.form1.BeginInvoke(new Action(SetStatus), new object[] { });
            Form1.form1.EndInvoke(result);
        }
        else
        {
            if (bool_AutoRun)
            {
                // 更新 DataTable
                MPU.dt_MainTable.Rows[int_ThreadNum + index]["Static"] = str_Data[index];

                // 刷新 DataGridView 畫面
                dataGridView1.Refresh();
            }
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

參考看看囉~

我要發表回答

立即登入回答