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

foreach循环执行SQL请求时如何实现实时更新的进度条

核心原因

WPF的UI渲染和事件回调都运行在UI主线程,你当前的SQL执行和foreach循环都是同步逻辑,会阻塞UI线程,导致进度条的属性变更无法被实时渲染,只有整个UID_SendRestore_Click方法执行完毕后,UI线程才会一次性处理所有待更新的UI变更,所以你会看到进度条直接填满。

修改方案

我们通过async/await异步执行SQL请求,避免阻塞UI线程,每次SQL执行完成后实时更新进度条,修改后的代码如下:

// 首先给Click方法加上async修饰符
private async void UID_SendRestore_Click(object sender, RoutedEventArgs e)
{
    Bd_IsUpdate = isAnyChecked;
    if (RestoreDatabase.IsChecked == false && ReorganizeDatabase.IsChecked == false)
    {
        MessageBox.Show("Vous devez sélectionner au minimum un choix à appliquer", "Absence de sélection", MessageBoxButton.OK, MessageBoxImage.Exclamation);
        return;
    }
    // 先把进度条最大值一次性设置好,不用放在循环里重复赋值
    pbStatus.Maximum = isAnyChecked;
    pbStatus.Value = 0;
    
    // 把选中的项先查出来存好,避免循环中反复遍历数据源
    var checkedItems = (from DBtoRestore x in dgDBtoRestore.Items
                       where x.IsChecked
                       select x).ToList();

    foreach (DBtoRestore item in checkedItems)
    {
        if (RestoreDatabase.IsChecked == true)
        {
            try
            {
                // 建议数据库连接用using声明,用完自动释放,不要复用全局连接对象更安全
                using (SqlConnection cnx = new SqlConnection())
                {
                    if (cmbAuthentification.Text.Equals("Windows"))
                    {
                        cnx.ConnectionString = "Server = " + txtServerName.Text + "; Integrated Security = SSPI;";
                    }
                    else if (cmbAuthentification.Text.Equals("SQL Server"))
                    {
                        cnx.ConnectionString = "Server = " + txtServerName.Text + "; User ID =" + txtUserID.Text + "; Password=" + txtUserPwd.Password + ";";
                    }
                    // 异步打开连接,不阻塞UI
                    await cnx.OpenAsync();
                    using (SqlCommand cmd = new SqlCommand())
                    {
                        cmd.Connection = cnx;
                        cmd.CommandText = @"USE [" + item.CUID_dbname + "];" + ...;
                        cmd.CommandTimeout = 0;
                        // 异步执行SQL,执行期间UI线程可以正常渲染进度条
                        SqlDataReader dr = await cmd.ExecuteReaderAsync();
                        dr.Close();
                    }
                    cnx.Close();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "OOoopssss !!!", MessageBoxButton.OK, MessageBoxImage.Hand);
                Bd_IsUpdate++;
            }
        }
        // 每次处理完一个项,更新进度条值,await之后的代码默认回到UI线程执行,可直接操作UI
        Bd_IsUpdate--;
        pbStatus.Value += 1;
    }
}
关键说明
  • 给UID_SendRestore_Click添加async修饰符,所有IO操作(打开连接、执行SQL)都使用对应的异步API(OpenAsync、ExecuteReaderAsync)搭配await调用,执行过程不会阻塞UI线程
  • 进度条的更新放在每次SQL处理完成之后,此时UI线程处于空闲状态,会立即渲染进度条变更
  • 建议不要复用全局的SqlConnection、SqlCommand对象,每次操作新建连接并通过using自动释放,避免多线程操作或异常场景下的资源泄漏

注意:该方案要求.NET Framework版本 >=4.5 或使用.NET Core/.NET 5+,默认已支持SqlClient的异步API。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 17:57:04