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

C#中MySQL批量插入循环致窗口冻结,需实时显示计数

解决C# MySQL循环插入时UI冻结与实时计数更新问题

问题根源

你的代码在主线程里执行18k+条同步数据库插入操作,主线程被长时间占用,根本没时间处理UI刷新消息,导致窗口冻结,计数只能等整个循环结束才显示。另外,直接拼接SQL字符串存在严重的SQL注入风险,且单条循环插入效率极低,会进一步拖慢操作时长。

优化方案

1. 将数据库操作移至后台线程

用异步任务释放主线程,让它专注处理UI交互与刷新,避免冻结。

2. 改用参数化批量插入

既彻底避免SQL注入,又大幅减少数据库交互次数,提升插入速度。

3. 安全更新UI控件

UI控件仅能在主线程修改,后台线程更新时必须切换回主线程操作。

修改后的完整代码

private async void btnStartInsert_Click(object sender, EventArgs e)
{
    // 禁用按钮防止重复触发
    btnStartInsert.Enabled = false;
    int currentCount = 0;
    int batchSize = 100; // 每100条提交一次,可根据实际调整

    try
    {
        // 把耗时的数据库操作放到后台线程执行
        await Task.Run(() =>
        {
            using (var conn = new MySqlConnection(connectionString))
            {
                conn.Open();
                // 使用参数化SQL,禁止直接拼接字符串
                string insertSql = "INSERT INTO db(val1, val2, val3, val4, val5) VALUES (@val1, @val2, @val3, @val4, @val5)";
                
                using (var cmd = new MySqlCommand(insertSql, conn))
                {
                    // 预先定义参数,避免重复创建
                    cmd.Parameters.Add("@val1", MySqlDbType.VarChar);
                    cmd.Parameters.Add("@val2", MySqlDbType.Int32);
                    cmd.Parameters.Add("@val3", MySqlDbType.Decimal);
                    cmd.Parameters.Add("@val4", MySqlDbType.DateTime);
                    cmd.Parameters.Add("@val5", MySqlDbType.VarChar);

                    int batchCounter = 0;
                    foreach (var item in values)
                    {
                        // 假设item是包含5个字段的自定义对象,自行替换为实际属性赋值
                        cmd.Parameters["@val1"].Value = item.Val1;
                        cmd.Parameters["@val2"].Value = item.Val2;
                        cmd.Parameters["@val3"].Value = item.Val3;
                        cmd.Parameters["@val4"].Value = item.Val4;
                        cmd.Parameters["@val5"].Value = item.Val5;

                        cmd.ExecuteNonQuery();
                        currentCount++;
                        batchCounter++;

                        // 每攒够batchSize条数据就提交一次,同时更新UI计数
                        if (batchCounter >= batchSize)
                        {
                            conn.Commit();
                            UpdateCount(currentCount);
                            batchCounter = 0;
                        }
                    }

                    // 提交最后一批不足batchSize的数据
                    if (batchCounter > 0)
                    {
                        conn.Commit();
                        UpdateCount(currentCount);
                    }
                }
                conn.Close();
            }
        });

        MessageBox.Show("所有数据插入完成!");
    }
    catch (Exception ex)
    {
        MessageBox.Show("出错了:" + ex.ToString());
    }
    finally
    {
        // 恢复按钮可用状态
        btnStartInsert.Enabled = true;
    }
}

// 专门用于更新UI计数的方法,确保在主线程执行
private void UpdateCount(int count)
{
    if (textBox1.InvokeRequired)
    {
        // 当前非主线程,切换回主线程执行更新
        textBox1.Invoke(new Action<int>(UpdateCount), count);
    }
    else
    {
        textBox1.Text = count.ToString();
        // 强制刷新控件,保证计数实时显示
        textBox1.Refresh();
    }
}

关键说明

  • 异步后台任务:async/await + Task.Run让数据库操作在后台运行,主线程不被阻塞,UI可正常响应和刷新。
  • 批量插入:每100条提交一次(可调整batchSize),比单条插入效率提升数倍,尤其适合大数量级数据。
  • 安全UI更新:UpdateCount方法通过InvokeRequired判断线程,避免跨线程操作异常,Refresh强制刷新控件确保计数实时显示。
  • 参数化查询:彻底杜绝SQL注入风险,同时数据库可缓存查询计划,进一步优化性能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 23:33:17