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

Form间DataGridView批量数据传输的性能优化问题

批量数据从Form2传输到Form1的DataGridView性能优化方案

问题背景

从Form1打开Form2,Form2的DataGridView展示数据库搜索结果,其中带复选框列用于选择要返回给Form1的DataGridView的记录。当前少量数据传输速度正常,但200条记录就耗时明显,后续需处理3000条以上数据,需要优化传输性能。

当前实现方式:Form1定义接口,遍历Form2的DataGridView,验证复选框状态和手机号格式,符合要求则调用接口将DataGridViewRow传给Form1插入。

当前核心代码

Form2中的遍历与传输逻辑:

for (int i = 0; i < dgvResutadoBusquedaBA.Rows.Count; i++)
{
    if (Convert.ToBoolean(dgvResutadoBusquedaBA.Rows[i].Cells["agregar"].Value))
    {
        
        bool isMatach = Regex.IsMatch(dgvResutadoBusquedaBA.Rows[i].Cells["Telefono"].Value.ToString(), "^(3)(\\d{9})$");
        if (!isMatach)
        {
            codigosTelefonoError.Add(dgvResutadoBusquedaBA.Rows[i].Cells["codigo"].Value.ToString());
            TelefonoError.Add(dgvResutadoBusquedaBA.Rows[i].Cells["Telefono"].Value.ToString());
        }
        else
        {
            DataGridViewRow row1 = dgvResutadoBusquedaBA.Rows[i] as DataGridViewRow;
            interfaz1.tableDatosEntrantes(row1);                               
        }
    }
}

Form1的接口定义:

internal interface interfazDatosEntrantes
{
    void tableDatosEntrantes(DataGridViewRow row1);
}

tableDatosEntrantes方法接收DataGridViewRow并插入到Form1的DataGridView中。


优化方案

1. 批量传输数据,减少接口调用次数

当前每条合法记录都调用一次接口,频繁的方法调用和UI刷新是性能瓶颈。改为先收集所有合法数据,一次性传输给Form1。

  • 修改接口支持集合传输:
internal interface interfazDatosEntrantes
{
    void tableDatosEntrantes(List<DataGridViewRow> validRows);
}
  • Form2中先收集数据再批量调用:
var validRows = new List<DataGridViewRow>();
for (int i = 0; i < dgvResutadoBusquedaBA.Rows.Count; i++)
{
    var row = dgvResutadoBusquedaBA.Rows[i];
    if (Convert.ToBoolean(row.Cells["agregar"].Value))
    {
        string telefono = row.Cells["Telefono"].Value.ToString();
        bool isMatch = Regex.IsMatch(telefono, "^(3)(\\d{9})$");
        if (!isMatch)
        {
            codigosTelefonoError.Add(row.Cells["codigo"].Value.ToString());
            TelefonoError.Add(telefono);
        }
        else
        {
            validRows.Add(row as DataGridViewRow);
        }
    }
}
// 一次性传输所有合法数据
interfaz1.tableDatosEntrantes(validRows);

2. 暂停Form1的DataGridView UI更新

批量插入时,DataGridView每添加一行都会触发UI刷新,这是大数量下的主要耗时点。插入前关闭自动布局、自动列宽等设置,插入后再恢复。

Form1的tableDatosEntrantes方法修改:

public void tableDatosEntrantes(List<DataGridViewRow> validRows)
{
    // 暂停UI布局更新
    dgvForm1.SuspendLayout();
    // 临时关闭自动列宽(保留原有设置)
    var oldAutoSizeMode = dgvForm1.AutoSizeColumnsMode;
    dgvForm1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;

    foreach (var row in validRows)
    {
        // 直接复制单元格值添加,避免行对象的复杂操作
        dgvForm1.Rows.Add(row.Cells.Cast<DataGridViewCell>().Select(c => c.Value).ToArray());
    }

    // 恢复原有设置
    dgvForm1.AutoSizeColumnsMode = oldAutoSizeMode;
    dgvForm1.ResumeLayout();
}

3. 预编译正则表达式

当前每次验证手机号都创建新的Regex实例,预编译后可重复使用,提升验证速度。

在Form2中定义静态预编译的Regex:

private static readonly Regex TelefonoRegex = new Regex("^(3)(\\d{9})$", RegexOptions.Compiled);

验证时直接调用:

bool isMatch = TelefonoRegex.IsMatch(telefono);

4. 直接操作数据源而非DataGridViewRow

如果DataGridView绑定了DataTable等数据源,直接操作数据源比操作DataGridViewRow更高效。

  • Form2中直接筛选数据源的合法行:
var sourceTable = dgvResutadoBusquedaBA.DataSource as DataTable;
var validRows = sourceTable.AsEnumerable()
    .Where(row => Convert.ToBoolean(row["agregar"]))
    .Select(row => 
    {
        string telefono = row["Telefono"].ToString();
        if (TelefonoRegex.IsMatch(telefono))
            return row;
        else
        {
            codigosTelefonoError.Add(row["codigo"].ToString());
            TelefonoError.Add(telefono);
            return null;
        }
    })
    .Where(row => row != null)
    .CopyToDataTable();

interfaz1.tableDatosEntrantes(validRows);
  • 修改接口支持DataTable传输:
internal interface interfazDatosEntrantes
{
    void tableDatosEntrantes(DataTable validTable);
}
  • Form1中合并数据源:
public void tableDatosEntrantes(DataTable validTable)
{
    var targetTable = dgvForm1.DataSource as DataTable;
    dgvForm1.SuspendLayout();
    // 直接合并数据表,效率远高于逐行添加
    targetTable.Merge(validTable);
    dgvForm1.ResumeLayout();
}

5. 异步处理(可选)

针对超大规模数据,可将筛选验证逻辑放到后台线程,避免阻塞UI,提升用户体验。注意操作UI必须回到主线程。

Form2中使用异步处理:

await Task.Run(() => 
{
    // 后台线程执行数据筛选和验证,收集validRows或validTable
});
// 回到主线程执行数据传输
interfaz1.tableDatosEntrantes(validRows);

内容的提问来源于stack exchange,提问作者Jhonnatan Lopez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 06:11:15