首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

WinForms DataGridView 即時刷新資料效能優化

     編輯:程式設計綜合問答

WinForms DataGridView 大量資料即時更新效能優化指南

使用 Timer 輪詢方式每秒重新綁定 DataSource 到 DataGridView,會導致 UI 假死、閃爍、記憶體飆升。需從架構層面優化。

❌ 錯誤做法:定時器完整重繫結


// 這會導致嚴重效能問題
private void timer_Tick(object sender, EventArgs e) {
    DataTable dt = GetDataFromDB(); // 查詢資料庫
    dataGridView1.DataSource = dt;  // 完整重綁 -> UI 重繪、閃爍、假死
    dataGridView1.Refresh();
}

✅ 方案一:只更新異動資料 (推薦)

// 使用 BindingList 配合 INotifyPropertyChanged
public class StockItem : INotifyPropertyChanged {
    private string _symbol;
    private decimal _price;
    
    public string Symbol { get => _symbol; set { _symbol = value; OnPropertyChanged(); } }
    public decimal Price { get => _price; set { _price = value; OnPropertyChanged(); } }
    
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string name = null) {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}

// 表單載入時一次綁定
private BindingList _data = new BindingList();
dataGridView1.DataSource = _data;

// 背景執行緒只更新屬性值,UI 自動反映
Task.Run(async () => {
    while (running) {
        var updates = await GetLatestPricesAsync();
        foreach (var u in updates) {
            var item = _data.FirstOrDefault(x => x.Symbol == u.Symbol);
            if (item != null) item.Price = u.Price; // 觸發 UI 更新
        }
        await Task.Delay(1000);
    }
});

✅ 方案二:Virtual Mode 虛擬模式 (超大資料量)

dataGridView1.VirtualMode = true;
dataGridView1.RowCount = totalCount;

// 實作 CellValueNeeded 事件
private void dataGridView1_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e) {
    e.Value = GetCellData(e.RowIndex, e.ColumnIndex); // 按需載入
}

// 資料變更時只重繪受影響列
dataGridView1.InvalidateRow(rowIndex);

✅ 方案三:背景執行緒 + 批次更新

private async void RefreshDataAsync() {
    var newData = await Task.Run(() => GetDataFromDB()); // 背景查詢
    
    // UI 執行緒批次更新
    dataGridView1.SuspendLayout();
    dataGridView1.Rows.Clear();
    foreach (var row in newData) {
        dataGridView1.Rows.Add(row.ItemArray);
    }
    dataGridView1.ResumeLayout();
}

關鍵優化原則

問題原因解決方案
UI 假死UI 執行緒阻塞於資料庫查詢非同步查詢
閃爍完整重設 DataSource 觸發完整重繪增量更新 / VirtualMode
記憶體暴增重複建立 DataTable、未釋放重複使用集合、實作 IDisposable
選取遺失重綁定重置選取狀態保存/恢復 CurrentCell、SelectedRows

進階:使用第三方元件

  • Syncfusion SfDataGrid:高效能虛擬化、支援百萬列
  • DevExpress GridControl:伺服器模式、即時資料流
  • ComponentOne FlexGrid:虛擬模式、資料流繫結

核心心法:避免輪詢、避免完整重綁、避免 UI 執行緒做 I/O。採用資料繫結通知機制或虛擬模式,才能流暢處理即時資料。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved