You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF VB.NET中DataGridView加载大量SQL数据性能优化求助

WPF VB.NET DataGrid 数据填充性能优化方案

问题背景

从本地SQL Server存储过程取2000行123列数据仅需500-800ms,但填充到DataGrid(代码中写为DataGridView,WPF标准控件为DataGrid)时耗时长达约2分钟,现有代码如下:

数据访问层代码

Public Class SQL
    Private Const ConnectionString As String = "Data Source=(localdb)\TestVFE;Initial Catalog=testVFE;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"

    Private Shared Connection As New SqlConnection(ConnectionString)

    Public Shared Sub OpenConnection()
        If Connection.State = ConnectionState.Closed Then
            Connection.Open()
        End If
    End Sub

    Public Shared Sub CloseConnection()
        If Connection.State = ConnectionState.Open Then
            Connection.Close()
        End If
    End Sub

    Public Shared Function GetLast1000Rows() As DataTable
        OpenConnection()
        Dim cmd As New SqlCommand("GetLast1000Rows", Connection)
        cmd.CommandType = CommandType.StoredProcedure
        Dim adapter As New SqlDataAdapter(cmd)
        Dim results As New DataTable()
        adapter.Fill(results)
        CloseConnection()
        Return results
    End Function
End Class

主窗口代码

Class MainWindow
    Private Sub ResultsGrid_Loaded(sender As Object, e As RoutedEventArgs) Handles ResultsGrid.Loaded
        Dim dataTable As DataTable = SQL.GetLast1000Rows
        ResultsGrid.RowHeaderStyle = DataGridViewRowHeadersWidthSizeMode.EnableResizing
        ResultsGrid.ItemsSource = dataTable.DefaultView
    End Sub
End Class

优化方案

1. 异步加载数据,避免UI线程阻塞

UI线程被同步数据操作占用会导致界面假死,感知耗时变长,改用异步模式:

修改数据访问层为异步方法:

Public Shared Async Function GetLast1000RowsAsync() As Task(Of DataTable)
    ' 使用Using自动管理连接生命周期,避免共享连接的池问题
    Using conn As New SqlConnection(ConnectionString)
        Await conn.OpenAsync()
        Using cmd As New SqlCommand("GetLast1000Rows", conn)
            cmd.CommandType = CommandType.StoredProcedure
            Dim adapter As New SqlDataAdapter(cmd)
            Dim results As New DataTable()
            adapter.Fill(results)
            Return results
        End Using
    End Using
End Function

主窗口异步处理:

Private Async Sub ResultsGrid_Loaded(sender As Object, e As RoutedEventArgs) Handles ResultsGrid.Loaded
    ResultsGrid.IsEnabled = False ' 可选:禁用控件避免用户操作
    Try
        Dim dataTable As DataTable = Await SQL.GetLast1000RowsAsync()
        ResultsGrid.ItemsSource = dataTable.DefaultView
        ResultsGrid.RowHeaderStyle = DataGridViewRowHeadersWidthSizeMode.EnableResizing
    Finally
        ResultsGrid.IsEnabled = True
    End Try
End Sub

2. 优化DataGrid渲染性能

禁用不必要的自动布局和视觉效果,减少UI重绘:

Private Async Sub ResultsGrid_Loaded(sender As Object, e As RoutedEventArgs) Handles ResultsGrid.Loaded
    ' 加载前暂停布局,避免频繁重绘
    ResultsGrid.SuspendLayout()
    
    Dim dataTable As DataTable = Await SQL.GetLast1000RowsAsync()
    ResultsGrid.ItemsSource = dataTable.DefaultView
    
    ' 优化渲染设置
    ResultsGrid.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None ' 禁用自动列宽(或按需指定Fill/固定宽度)
    ResultsGrid.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.DisableResizing ' 不需要行头调整则禁用
    ResultsGrid.DoubleBuffered = True ' 开启双缓冲减少闪烁
    
    ResultsGrid.ResumeLayout() ' 恢复布局一次性渲染
End Sub

3. 开启UI虚拟化

WPF DataGrid支持UI虚拟化,仅渲染可见区域的行/列,大幅降低大数量数据的渲染压力,在XAML中配置:

<DataGrid x:Name="ResultsGrid" 
          EnableRowVirtualization="True"
          EnableColumnVirtualization="True"
          VirtualizingPanel.IsVirtualizing="True"
          VirtualizingPanel.VirtualizationMode="Recycling"/>

4. 精简返回数据

检查存储过程是否返回了非必要的列,仅返回DataGrid需要显示的字段,减少数据传输量和UI渲染负担。

5. 修复连接管理问题

原代码使用共享SqlConnection可能导致连接池异常,改用Using语句自动释放连接,确保连接正确回收。


内容的提问来源于stack exchange,提问作者Milos Dimitrijevic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 10:38:30