отображение прогресса при выполнении запроса

собственно есть метод, в котором выполняется запрос для "перегонки" файлов с одной базы в другую. Файлов много, программа подвисает и хочется чтобы отображался прогресс выполнения.

Такой метод:

private void TransferFiles()
        {
            using (SqlConnection conn = new SqlConnection(ConnectionString.Value))
            {
                try
                {
                    conn.Open();
                    string fullPath = System.Reflection.Assembly.GetAssembly(typeof(Form1)).Location;                    // Получаем полное местоположение exe файла сборки 
                    string theDirectory = Path.GetDirectoryName(fullPath);                                               // Получаем папку в котором он находится
                    DataTable dt = new DataTable();
                    string queryOpen = String.Format("select top {7} t1.id, t1.{0}, t2.{1} " +
                                                     "from {2}.dbo.{3} t1 " +
                                                     "left join {4}.dbo.{5} t2 on t1.id = t2.{6}",
                                                     ConnectionString.DoVarchar, colNameImageCmb.Text, ConnectionString.InitialCatalog, ConnectionString.TableNameText,
                                                     initialCatalogTxb.Text, tableNameCmb.Text, fieldCommunicationCmb.Text, numericNumberOfLines.Value);
                    if (!String.IsNullOrEmpty(tableNameCmb.Text) && !String.IsNullOrEmpty(colNameImageCmb.Text) && !String.IsNullOrEmpty(fieldCommunicationCmb.Text))
                    {
                        SqlCommand command = new SqlCommand(queryOpen, conn);
                        SqlDataReader reader = command.ExecuteReader();
                        dt.Load(reader);
                        reader.Close();
                        foreach (var item in dt.Select())
                        {
                            int fileId = (int)item["id"];
                            string fileName = (string)item[ConnectionString.DoVarchar];
                            byte[] fileContent = (byte[])item[colNameImageCmb.Text];

                            using (FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate))
                            {
                                fs.Write(fileContent, 0, fileContent.Length);
                            }
                            string queryLoad = String.Format("UPDATE {0} SET \"{1}\" = (SELECT * FROM OPENROWSET(BULK '{4}\\{2}', SINGLE_BLOB) AS x), " +
                                                             "{5} = (GetDate()) where \"id\" = {3}",
                                                                ConnectionString.TableNameText, ConnectionString.Filestream, fileName, fileId, theDirectory, ConnectionString.Datetime);
                            command = new SqlCommand(queryLoad, conn);
                            command.ExecuteNonQuery();
                        }
                    }
                    else
                        MessageBox.Show("Выберите все поля!");
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }

добавил прогресс и backgroundworker

  private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            for (int i = 0; i <= 100; i++)
            {
                Thread.Sleep(10);
                backgroundWorker1.WorkerReportsProgress = true;
                backgroundWorker1.ReportProgress(i);
            }
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            circularProgressBar1.Value = e.ProgressPercentage;
            progressLbl.Text = e.ProgressPercentage.ToString() + "%";
            if (progressLbl.Text == "100%")
            {
                MessageBox.Show("Копирование успешно завершено!");
            }
        }

вылетает ошибка и обрывается выполнение запроса

введите сюда описание изображения

но прогресс выполняется до 100%. Подскажите где ошибаюсь.


Ответы (1 шт):

Автор решения: Bulson

Надо бы использовать async/await. Вот небольшой пример как это делается.

пример работы программы

public partial class FormMain : Form
{
    private const string _conString = @"Data Source=(localdb)\MSSQLLocalDB;" +
        "Initial Catalog=AdventureWorks2016;Integrated Security=True;" +
        "Connect Timeout=60;Encrypt=False;TrustServerCertificate=False;" +
        "ApplicationIntent=ReadWrite;MultiSubnetFailover=False"; 

    public FormMain()
    {
        InitializeComponent();

        _buttonSelectFile.Click += ButtonSelectFile_Click;
        _buttonSave.Click += ButtonSave_Click;
    }

    private void ButtonSelectFile_Click(object sender, EventArgs e)
    {
        if (_saveFileDialog.ShowDialog() != DialogResult.OK)
            return;

        _textBoxFile.Text = _saveFileDialog.FileName;
    }

    private async void ButtonSave_Click(object sender, EventArgs e)
    {
        var file = _textBoxFile.Text;
        if (String.IsNullOrEmpty(file))
            return;

        //кнопки
        _buttonSave.Enabled = false;
        _buttonSelectFile.Enabled = false;

        //колбек отображения процесса записи в файл
        IProgress<int> progress = new Progress<int>(value =>
        {
            _progressBar.Value = value;
            _labelProc.Text = $"{value}%";
            _labelProc.Update();
        });

        try
        {
            await SaveTableAsync(progress, file);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message, "Ошибка",
                MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
        finally
        {
            //кнопки
            _buttonSave.Enabled = true;
            _buttonSelectFile.Enabled = true;
        }
    }

    private async Task SaveTableAsync(IProgress<int> progress, string file)
    {
        //двусоставный запрос к БД
        var request = @"SELECT COUNT(AddressID)
                       FROM[AdventureWorks2016].[Person].[Address];
                       SELECT AddressLine1
                       FROM[AdventureWorks2016].[Person].[Address]";

        using (var con = new SqlConnection(_conString))
        using (var cmd = con.CreateCommand())
        {
            cmd.CommandText = request;
            await con.OpenAsync();
            using (var reader = await cmd.ExecuteReaderAsync())
            {
                //получаем количество записей в таблице
                int countRecords = 0;
                if (reader.HasRows)
                {
                    await reader.ReadAsync();
                    countRecords = reader.GetInt32(0);
                }
                //если есть данные по второй части запроса
                if (await reader.NextResultAsync())
                {
                    //открываем файл на запись
                    using (var fs = File.OpenWrite(file))
                    {
                        //текущая запись (строка) в таблице
                        int currentRecord = 0;
                        //пока есть записи в таблице
                        while (await reader.ReadAsync())
                        {
                            //получаем столбец
                            var column = reader.GetString(0);
                            var bytes = Encoding.UTF8.GetBytes(column);
                            //пишем в файл
                            await fs.WriteAsync(bytes, 0, bytes.Length);

                            //вычисляем процент записанных записей
                            var percent = ++currentRecord * 100 / countRecords;
                            //обновляем прогрессбар и лейбл
                            progress?.Report(percent);
                        }
                    }
                }
            }
        }
    }

}

Пример целиком здесь.

→ Ссылка