簡體   English   中英

綁定到DataGridView.Datasource時加載DataTable慢

[英]Loading DataTable Slow When Bound to DataGridView.Datasource

我一直在搜索,我無法想出這一個。 我正在開發一個Winforms UI,它正在拉動我需要在DataGridView中顯示的大量行。 我已經閱讀了有關限制行數和分頁的所有內容,我完全沒有辦法做到這一點。 基本上我正在編寫我在Codeplex上編寫的SQL Server 2008擴展事件管理器的TargetDataViewer控件。

http://extendedeventmanager.codeplex.com/

基於特定目標以及它如何呈現數據,我只能做我能做的事情。 我想要做的是將從目標讀取的數據流式傳輸到DataGridView,類似於Profiler或SQL Server Management Studio在流入時顯示數據的方式。我重寫了很多代碼,並使用BackgroundWorker提取數據並將其處理為DataTable。 如果我沒有設置DataGridView.DataSource = DataTable,我可以在幾分鍾內將300K +行數據加載到DataTable中,它確實運行得很快。 一旦我將DataTable添加到DataSource,它就會慢慢停止(而不是幾分鍾,相同的300K行可能需要1/2小時)。

我知道問題不是我的處理代碼,它特定於綁定到DataGridView.DataSource,我有時間碼來證明這一點。 我無法弄清楚如何解決這個問題。 對於性能,我可以在加載數據后將控件綁定到DataTable,但這是一個非常糟糕的用戶體驗。 我看到很多人在加載數據時抱怨DataGridView的性能影響,所以這可能只是我遇到的限制? 有任何想法嗎?

考慮當您從DataReader填充一行未綁定的DataTable時會發生什么:創建DataRow ,從DataReader填充並添加到Rows集合。 然后,當您創建綁定時, DataGridView從表中提取數據並在屏幕上構建視圖。

填充DataTable時會發生什么?它啟用了與DataGridView的綁定? 一堆亂七八糟的事件處理。 每次更改綁定屬性時,都會引發屬性更改事件,綁定控件會處理它。 這不會發生300,000次,每發生300,000次。

如果你關閉它,並且偶爾只更新綁定控件怎么辦? 看看這個方法:

private void PopulateDataTable()
{
    int rowCount = 10000;

    bindingSource1.RaiseListChangedEvents = false;
    for (int i = 0; i < rowCount; i++)
    {
        DataRow r = DT.NewRow();
        for (int j = 0; j < ColumnCount; j++)
        {
            r[j] = "Column" + (j + 1);
        }
        DT.Rows.Add(r);

        if (i % 500 == 0)
        {
            bindingSource1.RaiseListChangedEvents = true;
            bindingSource1.ResetBindings(false);
            Application.DoEvents();
            bindingSource1.RaiseListChangedEvents = false;
        }
    }
    bindingSource1.RaiseListChangedEvents = true
}

您必須調用ResetBindings來強制更新綁定控件。 這需要時間,因為您無法DataGridViewRow構建DataGridViewRow對象的成本,但取消事件是一項重大改進。 在我的機器上,如果我填充綁定到DataGridView的10列10000行DataTable ,則需要2900毫秒。 如果我在整個時間內關閉數據綁定,則需要155毫秒。 如果我每500行重置一次綁定,則需要840毫秒。

當然,如果我填充300,000行表,我不會每500行重置綁定; 我可能會在500行標記處執行一次,然后將其關閉直到操作完成。 但即使你這樣做,你也需要經常調用Application.DoEvents ,以便UI可以響應事件。

編輯

不要緊,關於Application.DoEvents ; 如果您在后台任務中填充表格,則不需要這樣做。

但是,您確實需要確保在BackgroundWorkerProgressChanged事件處理程序中重置綁定,而不是在DoWork方法中重置綁定。 如果您實際讓用戶在另一個線程上填充其數據源時在綁定的DataGridView 編輯數據,那么您將體驗到一個受傷的世界。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM