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

C#多线程MySQL备份下自增变量绑定DataGridView同步更新进度实现问询

实现方案

你遇到的问题核心是多线程共用实例导致属性覆盖、foreach闭包捕获异常、进度回调无对应行标识三个问题,以下是可直接落地的修改方案:


1. 核心逻辑说明

  • 每个线程对应独立的mysqlUtils实例,避免多线程并发修改同一个实例的属性
  • 用Interlocked.Increment实现线程安全的自增序号,保证每个线程拿到唯一的行索引
  • 解决foreach循环变量的闭包捕获问题,避免所有线程拿到最后一行的参数
  • 跨线程更新UI时通过Invoke封送到UI线程执行,避免控件操作异常

2. Form.cs 代码修改

private void button1_Click(object sender, EventArgs e)
{
    restoreUI();
}

public void restoreUI()
{
    // 初始化自增序号,初始值-1,第一次自增后得到0,符合第一个线程序号为0的要求
    int datagridIterate = -1;
    foreach(DataGridViewRow row in dataGridView1.Rows)
    {
        // 跳过DataGridView的空白新行模板
        if (row.IsNewRow) continue;
        // 每个线程创建独立的mysqlUtils实例,避免属性互相覆盖
        mysqlUtils msu = new mysqlUtils();
        // 线程安全自增,拿到当前线程对应的行号
        int currentIterate = Interlocked.Increment(ref datagridIterate);
        // 将行号绑定到当前mysqlUtils实例
        msu.RowIndex = currentIterate;
        // 解决foreach闭包问题:创建局部变量存储当前行,不要直接使用循环变量row
        DataGridViewRow currentRow = row;
        Thread t = new Thread(() =>
        {
            msu.Restore(currentRow.Cells[1].Value?.ToString(), server.Text, username.Text,
                pwd.Text, currentRow.Cells[0].Value?.ToString());
        });
        t.Start();
    }
}

// 新增UI进度更新方法,处理跨线程更新逻辑
public void updateProgressValue(int rowIndex, int total, int cur)
{
    if (dataGridView1.InvokeRequired)
    {
        // 跨线程时自动封送到UI线程执行
        dataGridView1.Invoke(new Action(() => updateProgressValue(rowIndex, total, cur)));
        return;
    }
    // 行号合法时更新对应单元格内容,可根据需要自定义显示格式
    if (rowIndex >= 0 && rowIndex < dataGridView1.Rows.Count)
    {
        dataGridView1.Rows[rowIndex].Cells[2].Value = $"已完成:{cur * 100 / total}% ({cur}/{total}字节)";
    }
}

3. Class1.cs 代码修改

namespace Utils
{
    public class mysqlUtils
    {
        // 新增行号属性,存储当前实例对应的DataGridView行索引
        public int RowIndex { get; set; }
        public int total;
        public int cur;

        public void Restore(string filename, string server, string user,
            string password, string db)
        {
            string constring = "server=" + server + ";user=" + user +
                ";pwd=" + password + ";database=" + db + ";";
            string file = "C:\\Users\\SQL FILES\\" + filename;
            using (MySqlConnection conn = new MySqlConnection(constring))
            {
                using (MySqlCommand cmd = new MySqlCommand())
                {
                    using (MySqlBackup mb = new MySqlBackup(cmd))
                    {
                        cmd.Connection = conn;
                        conn.Open();

                        mb.ImportInfo.IntervalForProgressReport = 50;

                        mb.ImportProgressChanged += updateProgress;
                        mb.ImportFromFile(file);

                        conn.Close();
                    }
                }
            }
        }

        // 修正:将updateProgress作为mysqlUtils的实例方法,绑定当前实例的行号
        private void updateProgress(object sender, ImportProgressArgs e)
        {
            total = (int)e.TotalBytes;
            cur = (int)e.CurrentBytes;
            Form4 form4 = (Form4)Application.OpenForms[0];
            // 传递当前实例对应的行号到Form的更新方法
            form4.updateProgressValue(RowIndex, total, cur);
        }
    }
}

内容的提问来源于stack exchange,提问作者Dat Cong Dinh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 11:57:03