Устранение подвисаний в формах

Устранение подвисаний в формахНередко бывает так, что процесс создания программы сопровождается сложными вычислениями, активно потребляющими ресурсы компьютера. Бывает и так, что их выполнение занимает довольно длительные промежутки времени. Такая ситуация приводит к тому, что существующая форма начинает постепенно подвисать. В таких случаях совершенно нечему удивляться, ведь для выполнения всех действий используется только один поток.

Выход из сложившейся ситуации заключается в создании дополнительного потока, способного заниматься различными ресурсоемкими вычислениями. В тех случаях, когда вычисления не имеют высокий уровень сложности, или у создателя программы совершенно отсутствует желание разбираться со всеми тонкостями, которыми наполнена работа с потоками, необходимо прибегнуть к использованию компонента, под названием 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(«Расчет окончен!»);

}

}

}

Категория: C#
Вы можете следить за комментариями с помощью RSS 2.0 ленты. Вы можете оставить комментарий, или трекбек с вашего сайта.
Оставить комментарий

XHTML: Вы можете использовать теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>