DevelNext – Асинхронность и многопоточность

JPHP позволяет использовать потоки и выполнять код в фоне, что позволяет избежать подтормаживания GUI при выполнении ресурсоёмких операций.

Если не создавать отдельные потоки, DevelNext будет исполнять всё в главном потоке: отрисовку графического интерфейса вперемешку с прочими вычислениями. При обработке “тяжёлых” файлов либо при других вычислениях, требующих много памяти или времени, отрисовка графического интерфейса произойдёт только после вычислений, что будет сопровождаться подтормаживанием и зависанием программы. Чтобы этого избежать – нужно все ресурсоёмкие вычисления выкидывать в отдельные потоки. Взаимодействие с формами и графическими элементами возможно только в главном потоке.

Для работы с потоками, есть класс Thread, для взаимодействия с главным (графическим) потоком существует класс UXApplication (он позволяет из любого потока вернуться в графический).

Использование конструктора

Допустим, необходимо загрузить изображение из Интернета в объект “изображение”. Для этого есть все необходимые элементы в конструкторе.

1. Добавим на форму объекты Изображение (image) и Кнопка (button), на кнопку добавим событие Действие => Изменить в конструкторе
Элементы на форме mainForm

2. В конструкторе сначала добавим индикатор загрузки (preloader), загрузим изображение (нужно убрать галочку “в главном потоке”), а после загрузки уберём индикатор.

(клик увеличит изображение)

Если перевести действия в код:

После нажатия на кнопку, мы увидим сначала preloader, а по окончанию загрузки – изображение, и всё без лагов и подтормаживаний.
5-res

Только код

Мы рассмотрели возможность выполнения кода в фоне, используя конструктор. Следующая ситуация, необходимо скачать из Интернета список стран, распарсить его и отобразить в списке. В конструкторе недостаточно возможностей, поэтому придётся всё писать вручную.
Последовательность действий:

  • 1. Скачать список стран (можно получить из api контакта)
  • 2. Распарсить данные в массив (вк возвращает данные в формате json)
  • 3. Отобразить данные в виде списка

Пункты 1 и 2 необходимо выполнить в отдельном потоке, 3 – в главном.

Приступим.
Сначала создадим новый метод, который позволит выполнить код асинхронно (т.е. в отдельном потоке). В отдельном потоке будет выполнена функция $func, всё, что она вернёт, будет передано в функцию $callback, которая потом будет выполнена в главном потоке.

(в других проектах, если понадобится работа с потоками, можно использовать эту функцию)

Получаем список стран и парсим json данные.

Код есть, объединяем всё в один проект. Создаем элементы кнопка (button) и выпадающий список (combobox).
Элементы второй формы

Весь код формы:

После нажатия на кнопку появится индикатор, когда данные загрузятся, индикатор исчезнет
Результат демо 2 - загрузка списка стран

В заключение

Проект со всеми примерами из этого поста: http://develnext.org/project/NOWKNcSHCJ

Код для создания асинхронных запросов:

4/5 - (6 голосов)

Добавить комментарий

  1. Sega:

    Как вновь запустить поток, после того как он выполнился? Мне нужна бесконечная рекурсия. На ум только страшные схемы приходят. Как это оформить кратко и прилично? Мне не нужно сразу много потоков, мне нужно именно по завершении одного, чтобы запускался второй такой же, потом третий и так далее. Если вызывать из функции, которая происходит по завершении, то мы не будем знать о самой этой функции для вызова нового потока, если делать ещё дополнительные глобальные переменные то выходят страшные схемы.

  2. Аноним:

    Спасибо за статью, а как разобрать данные полученные с таблицы.
    В мой таблице очень много данных, мне нужно отобрать по имени и фамилии, занести все в массив
    и вывести по ключам.
    К примеру: name=’Alex’, fname = ‘Smirnov’; У него есть Value = 1,2,3 и.т.д. Нужно отобрать с таблицы, показать все значения value. (В таблице может быть более 1000 имен и фамилии).
    В группе вк мне подсказали:
    $arr = arr::toArray($this->table->items);
    Json::toFile(‘./Config.json’,$arr);
    Далее нужно делать потоки, в котором нужно отобрать. Как сделать?

  3. Anubis:

    Отличный урок! Хорошо все расписал