Нередко бывает так, что процесс создания программы сопровождается сложными вычислениями, активно потребляющими ресурсы компьютера. Бывает и так, что их выполнение занимает довольно длительные промежутки времени. Такая ситуация приводит к тому, что существующая форма начинает постепенно подвисать. В таких случаях совершенно нечему удивляться, ведь для выполнения всех действий используется только один поток.
Выход из сложившейся ситуации заключается в создании дополнительного потока, способного заниматься различными ресурсоемкими вычислениями. В тех случаях, когда вычисления не имеют высокий уровень сложности, или у создателя программы совершенно отсутствует желание разбираться со всеми тонкостями, которыми наполнена работа с потоками, необходимо прибегнуть к использованию компонента, под названием backgroundworker. Он представлен отдельным классом, отображаемым в виде отдельного готового потока, для работы которого может быть использован фоновый режим. Далее последует пример, который описывает один из вариантов работы с данным классом. Не нужно забывать, что в форму должны быть добавлены дополнительные компоненты, в виде бэкграундворкеров.
using System;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;
namespace Program
{
public partial class Form1 : Form
{
public int global1; // Используем для передачи одного из результатов фонового расчета в форму для отображения
public Form1()
{
InitializeComponent();
// На форму должен быть добавлен компонент backgroundWorker1
// ПРЕДВАРИТЕЛЬНАЯ ПОДГОТОВКА
// DoWork требуется для запуска длительной задачи (метода) в фоновом потоке
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
// RunWorkerCompleted требуется для изменения элементов формы, после окончания расчета (например, результаты отобразить)
backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
// ProgressChanged вызывается каждый раз, когда в процессе расчета нужно что-нибудь поменять на форме.
// Например, изменить значение прогрессбара или какой-нибудь метки и т.п.
// Чтобы вызвать ProgressChanged используется метод ReportProgress c одним или двумя параметрами
// Например, backgroundWorker1.ReportProgress(n, «Working…»); или backgroundWorker1.ReportProgress(n);
backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
// WorkerReportsProgress нужно установить в true, чтобы пользоваться методом ReportProgress
backgroundWorker1.WorkerReportsProgress = true;
}
// Изменяет элементы формы в фоновом потоке
// Для вызова этого метода используется метод ReportProgress
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
toolStripProgressBar1.Value = e.ProgressPercentage; // Меняю данные прогрессбара
toolStripStatusLabel1.Text = (String)e.UserState; // Меняю значение метки
}
// Расчет запускается при нажатии на кнопку button1
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false; // На время расчета блокируем опасные кнопки
toolStrip1.Enabled = false;
backgroundWorker1.RunWorkerAsync(); // ЗАПУСКАЕМ ВЫЧИСЛЕНИЯ В ФОНОВОМ ПОТОКЕ!!!!
}
// Точка запуска фоновых расчетов
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
Calc(); // Вызываем метод с расчетами
// или прямо тут можно что-то считать =)
}
// Метод с расчетами
private void Calc()
{
int bigNumber = 77777777;
for (int i = 1; i < bigNumber; i++)
{
int n = (int)i * 100 / bigNumber; // вычисляем значение % для прогрессбара
String s = «Выполнено » + n + «% расчета»;
backgroundWorker1.ReportProgress(n, s); // Отправляем данные в ProgressChanged
}
int global1 = i; // данные переменной global1 потом используем по окончании расчета для изменения формы
// Результаты расчета можно вернуть и другим способом-
// из метода backgroundWorker1_RunWorkerCompleted (читай документацию по BackgroundWorker)
backgroundWorker1.ReportProgress(100, «Расчет завершен!»); // Выводим данные на форму
}
// Вызывается сразу после завершения расчетов (выходе из backgroundWorker1_DoWork)
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
button1.Enabled = true; // После окончания расчета разблокируем опасные кнопки
toolStrip1.Enabled = true;
label2.Text = «По окончанию расчета перешли к числу» + global1;
MessageBox.Show(«Расчет окончен!»);
}
}
}