【问题标题】:Progress bar with a foreach带有 foreach 的进度条
【发布时间】:2021-10-10 13:14:28
【问题描述】:

在 foreach 中,我执行 sql 请求。我想要一个进度条来显示每个请求的进度。

这是我的代码中包含 foreach 的一部分:

        private void CUID_allcheckbox_Unchecked(object sender, RoutedEventArgs e)
    {
        isAnyChecked = 0;
        UID_SendRestore.IsEnabled = false;

        foreach (DBtoRestore item in from DBtoRestore x in dgDBtoRestore.Items select x)
        {
            item.IsChecked = false;
            dgDBtoRestore.Items.Refresh();
        }
    }
    private 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;
        }

        foreach (DBtoRestore item in from DBtoRestore x in dgDBtoRestore.Items
                                     where x.IsChecked
                                     select x)
        {

            pbStatus.Maximum = isAnyChecked;
            Bd_IsUpdate--;

            if (RestoreDatabase.IsChecked == true)
            {
                try
                {
                    if (Cnx.State == ConnectionState.Open)
                    {
                        Cnx.Close();
                    }
                    if (cmbAuthentification.Text.Equals("Windows"))
                    {
                        SQL_Connection.ConnectionString = "Server = " + txtServerName.Text + "; Integrated Security = SSPI;";
                        
                        Cnx.ConnectionString = SQL_Connection.ConnectionString;
                    }
                    else if (cmbAuthentification.Text.Equals("SQL Server"))
                    {
                        SQL_Connection.ConnectionString = "Server = " + txtServerName.Text + "; User ID =" + txtUserID.Text + "; Password=" + txtUserPwd.Password + ";";
                        Cnx.ConnectionString = SQL_Connection.ConnectionString;
                    }
                    Cnx.Open();
                    Cmd.Connection = Cnx;
                    Cmd.CommandText =
                    @"USE [" + item.CUID_dbname + "];" + ...

                    Cmd.CommandTimeout = 0;
                    SqlDataReader dr = Cmd.ExecuteReader();

                    Cnx.Close();

                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "OOoopssss !!!", MessageBoxButton.OK, MessageBoxImage.Hand);
                    Bd_IsUpdate++;
                }
            }

我尝试了很多代码,但唯一的结果是请求结束时进度条已满...

欢迎帮助。

【问题讨论】:

  • 您的应用程序“挂起”在 foreach 循环上,因此您看不到运行进度,只有在完成时才会显示。您应该在其他线程中或异步运行您的工作。将整个循环放入单独的方法或任务中,并通过new Thread().Start()Task.Run 运行此方法。并添加代码以将进度条值设置到 foreach 循环中。
  • 类似的东西? Task.Run(() => { for (int i = 0; i < pbStatus.Maximum; i++) { this.Dispatcher.Invoke(() => { pbStatus.Value = i; }); } });
  • 是的,但是您需要计算当前进度的百分比或将 ProgressBar.MaxValue 设置为已检查的项目数。

标签: c# wpf progress-bar


【解决方案1】:

首先,您的foreach 循环在主线程中运行,并且可以“挂起”您的应用程序直到完成。您应该在其他线程中运行它(检查 Thread.Start()Task.Run() 方法)以使应用程序可用且响应迅速。

出于进度更新目的,您可以使用for 循环而不是foreach 循环并且:

  • 使用迭代作为进度条的当前值。在这种情况下,您应该在每次循环之前更改 ProgressBar.MaxValue,具体取决于要迭代的项目数。
  • 计算百分比而不是直接金额。

示例1(将for循环的当前迭代设置为进度条值):

private void YourButton_Click(object sender, RoutedEventArgs e)
{
    List<string> sqlQueries = new List<string>(10);

    // Set maximum value of your progress bar as
    // amount of items which you will iterate in loop
    progressBar.MaxValue = sqlQueries.Count; // 10
    progressBar.Value = 0; // Reset current value to 0

    // Run loop in other thread
    Task.Run(async () =>
    {
        for (int i = 0; i < sqlQueries.Count; i++)
        {
            string sqlQuery = sqlQueries[i];

            using (SqlCommand command = new SqlCommand())
            {
                command.CommandText = sqlQuery;

                using (SqlDataReader reader = await command.ExecuteReaderAsync())
                {
                    // Do read
                }
            }

            // Update progress by setting current iteration as current value
            Dispatcher.Invoke(() => progressBar.Value = i); // 1/10, 2/10, 3/10 etc...
        }
    });
}

示例2(计算进度百分比):

private void YourButton_Click(object sender, RoutedEventArgs e)
{
    List<string> sqlQueries = new List<string>(10);

    // DO NOT CHANGE maximum value of your progress bar
    // progressBar.MaxValue = sqlQueries.Count;
    progressBar.Value = 0; // Reset current value to 0

    // Run loop in other thread
    Task.Run(async () =>
    {
        for (int i = 0; i < sqlQueries.Count; i++)
        {
            string sqlQuery = sqlQueries[i];

            using (SqlCommand command = new SqlCommand())
            {
                command.CommandText = sqlQuery;

                using (SqlDataReader reader = await command.ExecuteReaderAsync())
                {
                    // Do read
                }
            }

            // Calculate a simple percentage
            int progressPercentage = (int)Math.Round(i * 100 / sqlQueries.Count);
            // Update progress with calculated percentage
            Dispatcher.Invoke(() => progressBar.Value = progressPercentage); // 10%, 20%, 30% etc...
        }
    });
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多