Таск что это в программировании
Перейти к содержимому

Таск что это в программировании

  • автор:

Дебажить, апрув, таска: мини-словарь сленга и профессиональной лексики программистов

Как часто от знакомых айтишников вы слышали загадочные термины, например, пушить или деплоить? Скорее всего, очень часто. Если вы только учитесь программированию или устроились на первую работу девелопером, то некоторые термины из IT-сферы могут оказаться незнакомыми. Мы создали мини-словарь сленга и профессиональной лексики: зная айтишные термины, новичкам будет проще освоиться на первой работе. В словарь постарались включить актуальную лексику айтишников (чаще всего это англицизмы), которой сегодня пользуются в IT-компаниях, но не брали такие очевидные слова, как «джун» или «галера», ведь сегодня эти термины стали широко известными. Ассайнить (от англ. assign — поручать) — назначать задачу на человека в качестве исполнителя. Пример употребления: Дебажить, апрув, таска: мини-словарь сленга и профессиональной лексики программистов - 1Аттачить (от англ. attach — прикрепить, загрузить) — используется в том же смысле, что и в английском языке. Например, можно отправлять письмо с прикрепленным файлом. Пример употребления: «Аттачни файл с документацией к письму». Апрув (от англ. approve — одобрять) — одобрение, утверждение или подтверждение чего-либо. Пример употребления: «Я не начну новую таску, так как жду от тебя апрув предыдущей». Бенч (от англ. bench — лавка, скамейка) — режим ожидания. «Программист на бенче» означает, что программист простаивает вхолостую в ожидании нового проекта/задания и, по факту, ничего не делает, но получает зарплату. Пример употребления: Дебажить, апрув, таска: мини-словарь сленга и профессиональной лексики программистов - 2Баг (от англ. bug) — ошибка в программе/коде, из-за которой результаты выполнения программы неправильные. Пример употребления: «Мы можем взять задачу с той багой в этот спринт?». Деплой (от англ. deploy — развертывание) — используется в программировании в своем прямом значении, то есть для обозначения развертывания (переноса) программного обеспечения на сервер или устройство, где оно должно функционировать. Пример употребления: «За свою карьеру я видел довольно много способов деплоя конфигов и уверен, что каждый может узнать об этом что-то новое». Билдить (от англ. to build — строить) — процесс, когда программный код преобразуется из языка программирования в язык машинных кодов. Пример употребления: Дебажить, апрув, таска: мини-словарь сленга и профессиональной лексики программистов - 3Дамп (от англ. dump — бросить, выкинуть) — файл с полной или частичной копией содержимого памяти компьютера или базы данных в момент создания данного файла. Очень часто дампы используются с целью создания и поддержания в актуальном состоянии системы бэкапа. Пример употребления: «Как ты создавал дамп: с помощью phpMyAdmin или через консольное окно?». Коммититься (от англ. commit — совершить) — коммит — это, как правило, кусок кода, влитый программистом в рамках решения данной задачи. Коммититься или закомититься — это соответственно добавить часть коммита в код. Пример употребления: «Я там закоммитил правки и запушил в мастер, можно деплоить». Дебажить (от англ. debug — отладка) — отладка кода, т.е. поиск и исправление ошибок в коде. Пример употребления: Дебажить, апрув, таска: мини-словарь сленга и профессиональной лексики программистов - 4Пингануть (от англ. ping — ударяться со стуком) — напоминать кому-либо о чем-либо, давать знать. Пример для употребления: «Пингани меня в конце дня, а то я могу забыть о нашем митинге». Рефакторинг кода (от англ. refactoring) — изменение исходного кода программы с целью упрощения и облегчения его понимания и дальнейшей поддержки. С помощью рефакторинга код становится чище, исправляются ошибки и «узкие места» в коде. Пример употребления: «Надо посмотреть код этого старого приложения и отрефакторить его». Стендап (от англ. stand-up meeting — «митинг на ногах») — по сути, это старая-добрая планерка или совещание. Традиционно стендап занимает 15 минут и проводится ежедневно в начале рабочего дня. Пример употребления: Дебажить, апрув, таска: мини-словарь сленга и профессиональной лексики программистов - 5Сторя (от англ. story — история) — корневая задача с описанием требований для разработки, она содержит в себе подзадачи, назначенные на разработчиков разных должностей. Пример употребления: «У нас по юзер-сторе надо вначале промокод ввести, а потом уже тотал на чекаут показывать». Фича (от англ. feature — характерная черта) — особенность, уникальное свойство. Существует популярное выражение — «Это не баг, а фича». Пример употребления: «Эта фича спасла игру и сделала ее популярной». Таска (от англ. task — задача) — задание или задача, которые ставят перед разработчиком. Пример употребления: Дебажить, апрув, таска: мини-словарь сленга и профессиональной лексики программистов - 6Фиксить или пофиксить (от англ. fix — исправить) — исправлять ошибки. Пример употребления: «Я быстро пофикшу этот баг, но завтра надо будет протестировать код». Как бы вы дополнили наш мини-словарь? Пишите в комментариях слова, которыми ежедневно пользуетесь в работе.

Task Класс

Пространство имен: System.Threading.Tasks Сборка: System.Threading.Tasks.dll Сборка: System.Runtime.dll Сборка: mscorlib.dll Сборка: netstandard.dll Исходный код: Task.cs Исходный код: Task.cs Исходный код: Task.cs

Некоторые сведения относятся к предварительной версии продукта, в которую до выпуска могут быть внесены существенные изменения. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.

Представляет асинхронную операцию.

public ref class Task : IAsyncResult
public ref class Task : IAsyncResult, IDisposable
public class Task : IAsyncResult
public class Task : IAsyncResult, IDisposable
type Task = class interface IAsyncResult
type Task = class interface IAsyncResult interface IDisposable
Public Class Task Implements IAsyncResult
Public Class Task Implements IAsyncResult, IDisposable

Наследование
Производный
Реализации

Комментарии

Дополнительные сведения об этом API см. в разделе Дополнительные примечания API для задачи.

Конструкторы

Инициализирует новую задачу Task с заданным действием.

Инициализирует новую задачу Task с заданным действием и токеном CancellationToken.

Инициализирует новую задачу Task с заданными действием и параметрами создания.

Инициализирует новую задачу Task с заданными действием и параметрами создания.

Инициализирует новую задачу Task с заданным действием и состоянием.

Инициализирует новый Task с указанным действием, состоянием и CancellationToken.

Инициализирует новую задачу Task с заданными действием, состоянием и параметрами.

Инициализирует новую задачу Task с заданными действием, состоянием и параметрами.

Свойства

Получает объект состояния, предоставленный при создании задачи Task, или значение null, если объект не предоставлен.

Возвращает задачу, которая уже завершилась успешно.

Возвращает объект TaskCreationOptions, используемый для создания данной задачи.

Возвращает идентификатор выполняющейся в настоящее время задачи Task.

Возвращает объект AggregateException, который привел к преждевременному завершению задачи Task. Если задача Task завершилась успешно или еще не создала ни одного исключения, возвращает значение null .

Предоставляет доступ к фабричным методам для создания и настройки экземпляров Task и Task .

Возвращает идентификатор указанного экземпляра Task.

Возвращает значение, указывающее, завершилось ли выполнение данного экземпляра Task из-за отмены.

Получает значение, указывающее, завершена ли задача.

Возвращает значение, указывающее, выполнена ли задача.

Возвращает значение, указывающее, завершилась ли задача Task из-за необработанного исключения.

Получает состояние TaskStatus данной задачи.

Методы

Настраивает объект типа awaiter, используемый для данного объекта Task.

Настраивает объект типа awaiter, используемый для данного объекта Task.

Создает продолжение, которое получает предоставленные вызывающей стороной сведения о состоянии и которое выполняется после завершения целевой задачи Task.

Создает продолжение, которое получает предоставленные вызывающей стороной сведения о состоянии и маркер отмены и которое выполняется асинхронно после завершения целевой задачи Task.

Создает продолжение, которое получает предоставленные вызывающей стороной сведения о состоянии и маркер отмены и которое выполняется после завершения целевой задачи Task. Продолжение выполняется на основе набора указанных условий и использует указанный планировщик.

Создает продолжение, которое получает предоставленные вызывающей стороной сведения о состоянии и которое выполняется после завершения целевой задачи Task. Продолжение выполняется на основе набора указанных условий.

Создает продолжение, которое получает предоставленные вызывающей стороной сведения о состоянии и выполняется асинхронно после завершения целевой задачи Task. Продолжение использует указанный планировщик.

Создает продолжение, которое выполняется асинхронно после завершения выполнения целевой задачи Task.

Создает продолжение, которое получает маркер отмены и которое выполняется асинхронно после завершения целевой задачи Task.

Создает продолжение, которое выполняется после завершения целевой задачи в соответствии с заданными параметрами TaskContinuationOptions. Продолжение получает маркер отмены и использует указанный планировщик.

Создает продолжение, которое выполняется после завершения целевой задачи в соответствии с заданными параметрами TaskContinuationOptions.

Создает продолжение, которое выполняется асинхронно после завершения выполнения целевой задачи Task. Продолжение использует указанный планировщик.

Создает продолжение, которое получает предоставленные вызывающей стороной сведения о состоянии, выполняется асинхронно после завершения целевой задачи Task и возвращает значение.

Создает продолжение, которое выполняется асинхронно после завершения целевой задачи Task и возвращает значение. Продолжение получает предоставленные вызывающей стороной сведения и маркер отмены.

Создает продолжение, которое выполняется на основе указанных параметров продолжения задачи после завершения целевой задачи Task и которое возвращает значение. Продолжение получает предоставленные вызывающей стороной сведения и маркер отмены, а также использует указанный планировщик.

Создает продолжение, которое выполняется на основе указанных параметров продолжения задачи после завершения целевой задачи Task. Продолжение получает предоставленные вызывающей стороной сведения.

Создает продолжение, которое выполняется асинхронно после завершения выполнения целевой задачи Task. Продолжение получает предоставленные вызывающей стороной сведения и использует указанный планировщик.

Создает продолжение, которое выполняется асинхронно после завершения целевой задачи Task и возвращает значение.

Создает продолжение, которое выполняется асинхронно после завершения целевой задачи Task и возвращает значение. Продолжение получает маркер отмены.

Создает продолжение, которое выполняется в соответствии с заданными параметрами и которое возвращает значение. Продолжение получает маркер отмены и использует указанный планировщик.

Создает продолжение, которое выполняется в соответствии с заданными параметрами и которое возвращает значение.

Создает продолжение, которое выполняется асинхронно после завершения целевой задачи Task и возвращает значение. Продолжение использует указанный планировщик.

Создает задачу, которая завершается через заданное количество миллисекунд.

Создает отменяемую задачу, которая завершается через заданное количество миллисекунд.

Создает задачу, которая завершается через заданное время.

Создает отменяемую задачу, которая завершается через заданное время.

Создает задачу, которая завершается через заданное время.

Создает отменяемую задачу, которая завершается через заданное время.

Освобождает все ресурсы, используемые текущим экземпляром класса Task.

Удаляет задачуTask, освобождая все используемые ею неуправляемые ресурсы.

Определяет, равен ли указанный объект текущему объекту.

Создает задачу Task, которая завершилась из-за отмены с помощью указанного маркера отмены.

Создает задачу Task, которая завершилась с указанным исключением.

Получает объект типа awaiter, используемый для данного объекта Task.

Служит хэш-функцией по умолчанию.

Возвращает объект Type для текущего экземпляра.

Создает неполную копию текущего объекта Object.

Ставит в очередь заданную работу для запуска в пуле потоков и возвращает объект Task, представляющий эту работу.

Ставит в очередь заданную работу для запуска в пуле потоков и возвращает объект Task, представляющий эту работу. Токен отмены позволяет отменить задачу, если она не была начата.

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

Ставит в очередь указанную работу для запуска в пуле потоков и возвращает прокси для задачи, возвращаемой функцией function . Токен отмены позволяет отменить задачу, если она не была начата.

Ставит в очередь заданную работу для запуска в пуле потоков и возвращает прокси для задачи Task(TResult) , возвращаемой function . Токен отмены позволяет отменить задачу, если она не была начата.

Ставит в очередь заданную работу для запуска в пуле потоков и возвращает прокси для задачи Task(TResult) , возвращаемой function .

Ставит в очередь заданную работу для запуска в пуле потоков и возвращает объект Task , представляющий эту работу. Токен отмены позволяет отменить задачу, если она не была начата.

Ставит в очередь заданную работу для запуска в пуле потоков и возвращает объект Task(TResult) , представляющий эту работу.

Синхронно выполняет задачу Task в текущем планировщике TaskScheduler.

Синхронно выполняет задачу Task в предоставленном планировщике TaskScheduler.

Запускает задачу Task, планируя ее выполнение в текущем планировщике TaskScheduler.

Запускает задачу Task, планируя ее выполнение в заданном планировщике TaskScheduler.

Возвращает строку, представляющую текущий объект.

Ожидает завершения выполнения задачи Task.

Ожидает завершения выполнения задачи Task. Ожидание завершается, если токен отмены отменяется до завершения задачи.

Ожидает завершения задачи Task в течение указанного числа миллисекунд.

Ожидает завершения выполнения задачи Task. Ожидание завершается, если время ожидания истекает или токен отмены отменяется до завершения задачи.

Ожидает завершения выполнения задач Task в течение указанного временного периода.

Ожидает завершения выполнения задачи Task.

Ожидает завершения выполнения всех указанных объектов Task.

Ожидает завершения выполнения всех указанных объектов Task, пока ожидание не будет отменено.

Ожидает завершения выполнения всех указанных объектов Task в течение указанного числа миллисекунд.

Ожидает завершения выполнения всех указанных объектов Task в течение указанного числа миллисекунд или до отмены ожидания.

Ожидает завершения выполнения всех указанных отменяемых объектов Task в течение указанного временного интервала.

Ожидает завершения выполнения любого из указанных объектов Task.

Ожидает завершения выполнения всех указанных объектов Task, пока ожидание не будет отменено.

Ожидает завершения выполнения любого из указанных объектов Task в течение указанного числа миллисекунд.

Ожидает завершения выполнения всех указанных объектов Task в течение указанного числа миллисекунд или до отмены токена отмены.

Ожидает завершения выполнения любого из указанных отменяемых объектов Task в течение указанного временного интервала.

Возвращает объект , Task который завершится после завершения или Task при запросе отмены указанного CancellationToken объекта.

Возвращает объект , Task который будет завершен по завершении или Task по истечении указанного времени ожидания.

Возвращает объект , Task который будет завершен после завершения, Task по истечении указанного времени ожидания или при запросе отмены указанного CancellationToken объекта.

Возвращает объект , Task который будет завершен по завершении или Task по истечении указанного времени ожидания.

Возвращает объект , Task который будет завершен после завершения, Task по истечении указанного времени ожидания или при запросе отмены указанного CancellationToken объекта.

Создает задачу, которая будет выполнена, когда все объекты Task в перечисляемой коллекции будут завершены.

Создает задачу, которая будет выполнена, когда все Task объекты в массиве будут завершены.

Создает задачу, которая будет выполнена, когда все объекты Task в перечисляемой коллекции будут завершены.

Создает задачу, которая будет выполнена, когда все Task объекты в массиве будут завершены.

Создает задачу, которая будет выполнена после выполнения любой из предоставленных задач.

Создает задачу, которая будет завершена после завершения любой из предоставленных задач.

Создает задачу, которая будет выполнена после выполнения любой из предоставленных задач.

Создает задачу, которая будет выполнена после выполнения любой из предоставленных задач.

Создает задачу, которая будет завершена после завершения любой из предоставленных задач.

Создает задачу, которая будет выполнена после выполнения любой из предоставленных задач.

Создает поддерживающий ожидание объект задачи, который асинхронным образом выдает возврат текущему контексту, когда его ожидают.

Явные реализации интерфейса

Возвращает дескриптор WaitHandle, который можно использовать для ожидания завершения задачи.

Получает значение, указывающее, синхронно ли выполнена операция.

Методы расширения

Представляет асинхронную операцию.

Представляет асинхронную операцию.

Представляет асинхронную операцию.

Представляет асинхронную операцию.

Представляет асинхронную операцию.

Представляет асинхронную операцию.

Представляет асинхронную операцию.

Представляет асинхронную операцию.

Представляет асинхронную операцию.

Представляет асинхронную операцию.

Ожидает завершения базовой операции DispatcherOperation в течение неограниченного времени.

Ожидает истечения заданного количества времени для базового DispatcherOperation.

Возвращает значение, указывающее, связан ли данный Task с DispatcherOperation.

Возвращает асинхронное действие среды выполнения Windows, представляющее запущенную задачу.

Применяется к

Потокобезопасность

Все члены Task, за исключением Dispose(), являются потокобезопасными и могут использоваться из нескольких потоков одновременно.

См. также раздел

  • Task
  • Библиотека параллельных задач (TPL)
  • Асинхронный шаблон на основе задач (TAP) в .NET: введение и обзор
  • Асинхронное программирование на основе задач
  • Примеры параллельного программирования с помощью .NET Core и .NET Standard

Совместная работа с нами на GitHub

Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.

Урок 25. Task. Что это такое и как формируется

В этом уроке узнаем, куда помещается Activity, пока его не видно. И откуда оно достается при нажатии кнопки назад. В хелпе об этом написано достаточно понятно. Я сделаю краткий перевод основной части этого хелпа и использую их схемы.

Task

Мы уже знаем, что приложение может содержать несколько Activity. И что Activity умеет вызывать Activity из других приложений с помощью Intent и Intent Filter. Если вы хотите отправить письмо из вашего приложения, вы вызываете Activity почтовой программы и передаете ей данные. Письмо уходит и вы возвращаетесь в ваше приложение. Создается ощущение, что все это происходило в рамках одного приложения. Такая «бесшовность» достигается за счет того, что оба Activity (ваше и почтовое) были в одном Task.

Прежде, чем продолжу объяснять, хочу сразу привести аналогию, чтобы тему легче было понять. В скобках я буду давать понятия-аналоги из Android.

Механизм организации Activity в Android очень схож по реализации с навигацией в браузере. Вы находитесь в одной вкладке(Task) и открываете страницы (Activity) переходя по ссылкам (Intent). В любой момент можете вернуться на предыдущую страницу, нажав кнопку Назад. Но кнопка Вперед отсутствует, т.к. страница, на которой была нажата кнопка Назад, стирается из памяти. И надо снова нажимать ссылку, если хотим попасть на нее. Если вам надо открыть что-то новое, вы создаете новую вкладку и теперь уже в ней открываете страницы, переходите по ссылкам, возвращаетесь назад. В итоге у вас есть несколько вкладок. Большинство из них на заднем фоне, а одна (активная, с которой сейчас работаете) – на переднем.

В итоге список аналогий браузера и Android таков:

Теперь вам будет более понятен текст про Task.

Task – группа из нескольких Activity, с помощью которых пользователь выполняет определенную операцию. Обычно стартовая позиция для создания Task – это экран Домой (Home).

Находясь в Home вы вызываете какое-либо приложение из списка приложений или через ярлык. Создается Task. И Activity приложения (которое отмечено как MAIN в манифест-файле) помещается в этот Task как корневое. Task выходит на передний фон. Если же при вызове приложения, система обнаружила, что в фоне уже существует Task, соответствующий этому приложению, то она выведет его на передний план и создавать ничего не будет.

Когда Activity_A вызывает Activity_B, то Activity_B помещается на верх (в топ) Task и получает фокус. Activity_A остается в Task, но находится в состоянии Stopped (его не видно и оно не в фокусе). Далее, если пользователь жмет Back находясь в Activity_B, то Activity_B удаляется из Task и уничтожается. А Activity_A оказывается теперь на верху Task и получает фокус.

В каком порядке открывались (добавлялись в Task) Activity, в таком порядке они и содержатся в Task. Они никак специально не сортируются и не упорядочиваются внутри. Набор Activity в Task еще называют back stack. Я буду называть его просто — стэк.

Схема (с офиц.сайта) демонстрирует пример:

В верхней части то, что видит пользователь. В нижней – содержимое Task. Видно, как при вызове новых Activity они добавляются в верх стэка. А если нажата кнопка Назад, то верхнее Activity из стэка удаляется и отображается предыдущее Activity.

Допустим у нас есть Task с несколькими Activity. Он на переднем фоне, мы с ним работаем сейчас.

— если мы нажмем кнопку Home, то ничего не будет удалено, все Activity сохранятся в этом Task-е, а сам Task просто уйдет на задний фон и его всегда можно будет вызвать оттуда, снова вызвав приложение, Activity которого является корневым для Task-а. Либо можно удерживать кнопку Home и мы увидим как раз список Task-ов, которые расположены на заднем фоне.

— если же в активном Task-е несколько раз нажимать кнопку Назад, то в итоге в стэке не останется Activity, пустой Task будет удален и пользователь увидит экран Home.

Там еще как всегда куча нюансов и сложностей, но мы пока остановимся на этом и в дебри не полезем. Этих знаний вполне хватит, чтобы ответить на вопросы предыдущего урока: почему на шаге 2 MainActivity исчезло с экрана, но осталось висеть в памяти и не было уничтожено? Ведь на шаге 3 было уничтожено ActivityTwo после того, как оно пропало с экрана. А на шаге 4 было в итоге уничтожено и MainActivity. Почему шаг 2 стал исключением?

Теперь вы знаете, почему. Потому, что на шаге 2 MainActivity осталось в стэке, а ActivityTwo вставилось на верх стэка и получило фокус. Ну а на шаге 3 и 4 были удалены Activity из верха стэка, в Task не осталось Activity, и мы увидели экран Home.

Если бы мы на шаге 3 нажали не Back, а Home, то Task с обоими Activity ушел бы задний фон и ничего не было бы уничтожено.

Paused

Теперь давайте откроем проект с прошлого урока P0241_TwoActivityState. Мы хотели поймать состояние Paused для Activity. Это состояние означает, что Activity не в фокусе, но оно видно, пусть и частично. Мы можем этого добиться, если присвоим диалоговый стиль для ActivityTwo. Оно отобразится как всплывающее окно и под ним будет частично видно MainActivity – оно и будет в статусе Paused. Давайте реализуем.

Для этого открываем AndroidManifest.xml, вкладка Application, находим там ActivityTwo и справа в поле Theme пишем такой текст: @android:style/Theme.Dialog

Все сохраняем и запускаем приложение.

MainActivity: onCreate()
MainActivity: onStart()
MainActivity: onResume()

MainActivity: onPause()
ActivityTwo: onCreate()
ActivityTwo: onStart()
ActivityTwo: onResume()

Видим, что не был вызван метод onStop для MainActivity, а значит приложение не было переведено в состояние Stopped и находится в режиме Paused.

ActivityTwo: onPause()
MainActivity: onResume()
ActivityTwo: onStop()
ActivityTwo: onDestroy()

MainActivity восстановилось одним лишь вызовом onResume, а onStart не понадобился, т.к. оно было в состоянии Paused, а не Stopped.

Мы четко увидели разницу между этим примером и им же на прошлом уроке. И MainActivity у нас был в состоянии Paused.

Далее можно нажать Back, а можно Home — вы уже знаете, что произойдет в обоих случаях. По логам можно убедиться в этом.

Чтобы вернуть ActivityTwo нормальный режим отображения, зайдите снова в манифест и удалите строку из поля Theme.

Кстати, у вас уже вполне достаточно знаний, чтобы создать приложение с кучей Activity, прописать вызовы и поиграться, посмотреть логи. Тем самым закрепите темы LifeCycle и Task.

На следующем уроке:

— вызываем Activity используя неявный вызов и Intent Filter

Присоединяйтесь к нам в Telegram:

— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Compose, Kotlin, RxJava, Dagger, Тестирование, Performance

— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

Что значит Task, когда говорят о языке программирования?

Доброй ночи, подскажите.
Как таковой Task перевело — задание.
Но как оно переводится по отношению к языку программирования?

  • Вопрос задан более трёх лет назад
  • 15631 просмотр

Комментировать
Решения вопроса 4

Зависит от конкретого языка программирования.

В некоторых языках этот термин не используется в самом языке — значит, относится в организации труда «задача, которую нужно решить».
В некоторых языках этот термин означает параллельно запускаемый поток выполнения.

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *