Member 13800132 Ответов: 3

Изменение значения индикатора выполнения не работает


Я пытаюсь увеличить свой индикатор выполнения при нажатии кнопки в моем приложении c#

В настоящее время я изложил его следующим образом;
private void backupbutton_Click(object sender, EventArgs e)
try {
                progressBar1.Value = 30;
                conn = new SqlConnection(connectionString);
                conn.Open();
                sql = "BACKUP DATABASE " + combodatabase.Text + " TO Disk = '" + "C:\\Temp" + "\\" +manualbackupname.Text+"-"+ combodatabase.Text + "-" + DateTime.Now.Ticks.ToString() + ".bak'";
                command = new SqlCommand(sql, conn);
                command.ExecuteNonQuery();
                conn.Close();
                conn.Dispose();
                progressBar1.Value = 100;  
}

Проблема, с которой я столкнулся, заключается в том, что я хочу, чтобы значение индикатора выполнения было установлено на 30 перед запуском скрипта, но он не регулирует индикатор выполнения до тех пор, пока сценарий SQL не будет завершен.

Не знаю, где я ошибаюсь, что-нибудь кто-нибудь может предложить?

Что я уже пробовал:

Я попытался переместить progressBar1.Value= 30; в разные точки раздела "try", но не смог заставить его работать.

F-ES Sitecore

Ваш код выполняется в том же потоке, что и пользовательский интерфейс, поэтому во время выполнения кода пользовательский интерфейс не будет обновляться. Что вам нужно сделать, так это запустить свой код в другом потоке в событии click, что позволит пользовательскому интерфейсу обновляться во время выполнения вашего SQL-кода. Обратите внимание, что вы не сможете получить доступ к компонентам пользовательского интерфейса из вашего нового потока, вам нужно будет использовать Invoke для обновления пользовательского интерфейса. Google для "winform new thread ui update", и вы найдете примеры того, как это сделать.

3 Ответов

Рейтинг:
1

OriginalGriff

Три вещи:
1) Никогда не объединяйте строки для построения SQL-команды. Это оставляет вас широко открытыми для случайной или преднамеренной атаки SQL-инъекции, которая может уничтожить всю вашу базу данных. Вместо этого всегда используйте параметризованные запросы.

Когда вы объединяете строки, вы вызываете проблемы, потому что SQL получает такие команды, как:

SELECT * FROM MyTable WHERE StreetAddress = 'Baker's Wood'
Цитата, добавленная пользователем, завершает строку в том, что касается SQL, и вы получаете проблемы. Но могло быть и хуже. Если я приду и наберу вместо этого: "x';DROP TABLE MyTable;--", то SQL получит совсем другую команду:
SELECT * FROM MyTable WHERE StreetAddress = 'x';DROP TABLE MyTable;--'
Которые SQL видит как три отдельные команды:
SELECT * FROM MyTable WHERE StreetAddress = 'x';
Совершенно правильный выбор
DROP TABLE MyTable;
Вполне допустимая команда "удалить таблицу"
--'
А все остальное-это комментарии.
Так оно и происходит: выбирает любые совпадающие строки, удаляет таблицу из базы данных и игнорирует все остальное.

Поэтому всегда используйте параметризованные запросы! Или будьте готовы часто восстанавливать свою БД из резервной копии. Вы ведь регулярно делаете резервные копии, не так ли?

2) Когда вы выполняете обработчик щелчка, больше никаких изменений с дисплеем не произойдет, пока он не выйдет: поток пользовательского интерфейса-это единственное, что выполняет событие Paint, и он связан с запуском вашего кода обработчика щелчка, тогда объекты не будут окрашены. Таким образом, первая настройка значения индикатора выполнения не сделает ничего полезного, так как она никогда не будет видна.

3) Вы можете переместить этот код (или, по крайней мере, фиксированную версию) в отдельный поток, но тогда вы не сможете напрямую получить доступ к элементам управления, таким как ProgressBar - попытка сделать это приведет к ошибке перекрестной потоковой передачи, поскольку только поток пользовательского интерфейса может иметь доступ к любому элементу управления.

Попробуйте использовать BackgroundWorker[^] - он обеспечивает механизм отчетности, предназначенный для отчетности о ходе работы.


Рейтинг:
1

Ravi Bhavnani

Вам лучше выполнить SQL-код в a BackgroundWorker как уже говорилось. Однако вы можете "обмануть", добавив эту строку после изменения любого элемента управления, чтобы вызвать обновление пользовательского интерфейса. Но я сильно не рекомендую этого делать, потому что пользователь также может закрыть содержащую форму при выполнении этой строки.

Application.DoEvents(); // allow the UI to update
/Рави


Рейтинг:
0

Richard Deeming

Если вы хотите сообщить о реальном ходе резервного копирования, вам, вероятно, придется использовать SMO:
Класс Резервного Копирования (Microsoft.SqlServer.Management.СМО) | Майкрософт Документы[^]
Резервное копирование и восстановление баз данных SQL Server программно с помощью SMO[^]

Альтернативой было бы использовать InfoMessage событие, как описано в этом потоке StackOverflow:
c# - резервное копирование базы данных SQL Server с прогрессом - переполнение стека[^]

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