Пример работы с BackgroundWorker C++ и заставляем работать Refresh


Потоки – одна из самых популярных тем в программировании. На самом деле в них ничего особо сложного нет, разобравшись с реализацией на одном языке программирования высокого уровня, вы уже и в другом сможете реализовать поток. Но есть несколько но. В этой заметке мы поговорим о реализации потоков с помощью встроенного элемента Visual studio C++ - это BackgroundWorker, а также при обход проблемы прорисовки и работы с элементами GUI.

Итак, попробуем на примере конкретной задачи разобраться потоками и отрисовкой их в визуал студио C++. Предположим, что на форме у нас есть pictureBox, на котором мы что-то рисуем. И нам требуется обновлять это что-то с частотой раз в полсекунды. Оператор Sleep(500) прекрасно справится с этой задачей, но до конца процесса визуализации мы увы, ничего не сможем сделать с нашей формой. Это некритично, если не требуется ставить паузу и процесс занимает немного времени. А нам нужна именно пауза.

В одной своей работе мне потребовалось сделать реализацию алгоритма сортировки Шелла с визуализацией оной. Алгоритм легко программируется на C++, визуализацию тоже, не мудрствуя лукаво, я сделал с помощью прямоугольников, высота которых была пропорционально чисел в массиве.



Теперь надо, собственно говоря, и поработать с потоками. Кидаем на форму элемент backgroundWorker1, а когда требуется его запустить, вызываем метод:

backgroundWorker1->RunWorkerAsync();
В самом потоке что-то делаем:

private: System::Void backgroundWorker1_DoWork(System::Object^  sender, System::ComponentModel::DoWorkEventArgs^  e) {
//что-то делаем, вычисляем и тд.
		Sleep (5000);
	}
	
И никакого подвисания не будет – в данном потоке выполняется одно, а форма и элементы управления работают.

Но у нас же визуализация алгоритма – давайте попробуем встроить в наш поток метод принудительной перерисовки pictureBox:

pictureBox1->Refresh();
И что мы видим? А ничего. Метод не будет отрабатывать. Не будет не выбрасывания ошибки, ничего – простой дойдет до этой строчки и перестанет работать данный поток. Почему так? В двух словах: нельзя управлять элементами формы из другого потока без некоторых ухищрений. Надо сделать так. Создадим еще один метод:

System::Void RefFre() {
   pictureBox1->Refresh();
}
И вызовем его через Invoke:

pictureBox1->Invoke(gcnew Action(this, &Form1:: RefFre));
Если надо передать какую либо переменную, то делаем так

pictureBox1->Invoke(gcnew Action<int>(this, &Form1:: RefFre), 0);
Соответственно, входящие параметры функции тоже надо изменить.

Вот теперь у нас все отлично скомпилируется, а перерисовка будет происходить тогда, когда надо – в фоновом потоке и расчет тогда же. Для остановки данного потока поставьте флаг WorkerSupportsCancellation true, а в нужном месте:

if (backgroundWorker1->CancellationPending) {
//прерываем, например…
break;
}
Вызов прерывания:

backgroundWorker1->CancelAsync();
Как видите, ничего особо сложного нет, но незнающий таких тонкостей человек может потратить немало времени для решения такой простой задачи. Если у вас что-то не получается, то вы можете написать мне. Не бесплатно, но недорого я помогу вам.

Кстати, напоминаю, что могу сделать для вас курсовые, лабораторные, практические и дипломные работы на C++, Java, C#, PHP. Так как я занимаюсь данной деятельностью не первый год, помогаю студентам, то у меня накопилась и продолжает копиться база решений (программ) по самым разным тематикам: от администрирования баз данных и до высшей математики. Так что заказывая программу для курсовой по программированию у меня, вы можете рассчитывать на самые низкие цены, если подобное я уже делал.
Автор этого материала - я - Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.

тегизаметки, си плюс плюс, visual studio, потоки, BackgroundWorker




Отправляя сообщение я подтверждаю, что ознакомлен и согласен с политикой конфиденциальности данного сайта.




Вычисление простых множителей в C#
Ошибки соединения с базой данных Laravel, или чудес не бывает
IDE NetBeans: возможности, советы и будущее