- •Графический интерфейс пользователей
- •Объектная модель программы
- •Основной элемент графического интерфейса – окна (windows)
- •Отношения между окнами
- •Типы окон
- •Программирование графического интерфейса (gui)
- •Содержание окна
- •Контекстное меню (ContextMenuStrip)
- •Библиотека api функций для рисования gdi32.Dll
- •Основной класс рисования Graphics
- •Основные методы класса Graphics
- •Получение объекта Graphics
- •Событие Paint
- •Выполнение рисования
- •Система координат. Система координат и единиц измерения
- •Классы для описания геометрических объектов
- •Операции с изображениями
- •Курсор мыши
- •Основные события устройства «мышь»
- •Размер окна
- •Свойство Anchor
- •Компоненты
- •Элементы управления для работы с принтером – Printing
- •Автоматизация создания программы
- •Окно списков ListBox
- •Коллекция элементов ListBox
- •Комбинированные окна ComboBox
- •Элемент CheckedListBox
- •Класс PictureBox
- •Элемент управления WebBrowser
- •Элемент управления ProgressBar
- •Элемент NumericUpDown
- •Подсказки – ToolTip
- •Процессы и потоки
- •Виды многопоточности:
- •Преимущества многопоточности
- •Случаи использования многопоточности:
- •Потоки в с#
- •Основные статические свойства:
- •Недостатки многопоточности
- •Методы управления потоками
- •Свойства потока.
- •Приоритеты потоков
- •Передача данных в ThreadStart
- •Управление потоками
- •Ресурсы, требующие синхронизации:
- •Простейшие методы блокировки.
- •Оператор lock
- •Класс Interlocked
- •Класс Monitor
- •Классы ManualResetEvent и AutoResetEvent
- •Атрибут [Synchronization]
- •Константы:
- •Минимально необходимые действия для использования BackgroundWorker:
- •Чтобы добавить отображение выполнения операции:
- •Чтобы иметь возможность отмены операции:
- •Задачи (класс Task)
- •Статусы задачи
- •Применение идентификатора задачи
- •Методы ожидания завершения задачи
- •Класс TaskFactory
- •Работа с данными в задаче
- •Вложенные задачи.
- •Механизм отмены задач.
- •Создание продолжения задачи
- •Шаблоны параллелизма Parallel
- •Метод For()
- •Досрочный выход из цикла
Вложенные задачи.
В коде задачи можно запускать вложенные задачи, которые могут быть дочерними и недочерними.
Недочерние задачи обладают независимостью от родительской задачи: родитель не дожидается завершения вложенной задачи, статусы задач не взаимосвязаны.
Дочерняя задача действительно является вложенной – родитель дожидается завершения дочерней задачи, статусы задач при исключениях взаимосвязаны.
Механизм отмены задач.
Встроенный механизм согласованной отмены задач позволяет унифицированным образом реализовывать корректное досрочное завершение выполнения задач.
Для реализации механизма отмены необходимо выполнить следующие шаги:
Создать объект CancellationTokenSource в области видимости метода, который порождает и запускает задачу.
Получить объект CancellationToken, через который осуществляется взаимодействие с задачей.
Передать объект CancellationToken при запуске задачи.
Реализовать в задаче процедуру отмены
При необходимости отмены вызвать метод Cancel().
Обработчик отмены задачи можно реализовать либо в самой задаче, либо назначить отдельный делегат, который будет вызываться при возникновении сигнала об отмене задачи.
Создание продолжения задачи
Одной из новаторских и очень удобных особенностей библиотеки TPL является возможность создавать продолжение задачи. Продолжение — это одна задача, которая автоматически начинается после завершения другой задачи.
Создать продолжение можно с помощью метода ContinueWith(), определенного в классе Task.
public Task ContinueWith(Action<Task> действие_продолжения)
где действие_продолжения обозначает задачу, которая будет запущена на исполнение по завершении вызывающей задачи. У делегата Action имеется единственный параметр типа Task. Следовательно, вариант делегата Action, применяемого в данном методе, выглядит следующим образом:
public delegate void Action<inT>(T obj)
В данном случае обобщенный параметр Т обозначает класс Task.
Шаблоны параллелизма Parallel
Одним из главных классов в TPL является System.Threading.Tasks.Parallel.
Этот класс поддерживает набор методов, которые позволяют выполнять итерации по коллекции данных (точнее, по объектам, реализующим IEnumerable<T>) в параллельном режиме.
Класс Parallel предоставляет след наиболее распространенные шаблоны параллельной обработки:
Parallel.Invoke: выполняет параллельно массив делегатов;
Parallel.For: параллельный эквивалент цикла for;
Parallel.ForEach: параллельный эквивалент цикла foreach.
Реализация шаблонов построена на задачах (tasks), поэтому при использовании методов Parallel поддерживаются механизмы отмены с помощью объекта CancellationToken и обработка исключений типа AggregateException. Важной особенностью шаблонов является "императивность". Оператор, следующий за вызовом метода класса Parallel, будет выполняться только после завершения всех задач, неявно созданных в методе.
Parallel.Invoke
Метод Invoke(), определенный в классе Parallel, позволяет выполнять один или несколько методов, указываемых в виде его аргументов. Он также масштабирует исполнение кода, используя доступные процессоры, если имеется такая возможность. Вызов:
public static void Invoke(params Action[] actions)
Выполняемые методы должны быть совместимы с делегатом Action. Следовательно, каждый метод, передаваемый методу Invoke() в качестве аргумента, не должен ни принимать параметров, ни возвращать значение.
Вызов метода позволяет "запустить" (добавить в очередь готовых к выполнению задач) несколько рабочих элементов и дождаться завершения их работы.
Пример вызова метода Invoke:
Parallel.Invoke(FuncOne, FuncTwo)
с помощью задач можно переписать следующим образом:
Task taskTwo = Task.Factory.StartNew(() => FuncTwo());
Task taskOne = Task.Factory.StartNew(() => FuncOne()); Task.WaitAll(taskOne, taskTwo);
Методы Parallel создают задачи не для каждого рабочего элемента, а для набора элементов, которые будут выполняться в одном потоке. Поток, в котором осуществляется вызов метода Invoke, также используется для обработки элементов.
Использовать метод Invoke вместо непосредственного манипулирования с задачами полезно, когда рабочие элементы можно запустить одновременно (нет какой-либо подготовительной работы перед каждой задачей) и вызывающий поток должен дождаться завершения работы всех рабочих элементов. Такая ситуация возникает в алгоритмах типа "разделяй и властвуй" (быстрая сортировка, обработка графов).
Метод Invoke() сначала инициирует выполнение, а затем ожидает завершения всех передаваемых ему методов. Это, в частности, избавляет от необходимости (да и не позволяет) вызывать метод Wait().
Все функции параллельного выполнения метод Invoke() берет на себя. И хотя это не гарантирует, что методы будут действительно выполняться параллельно, тем не менее, именно такое их выполнение предполагается, если система поддерживает несколько процессоров.
Кроме того, отсутствует возможность указать порядок выполнения методов от первого и до последнего, и этот порядок не может быть таким же, как и в списке аргументов.
В качестве аргументов метода Parallel.Invoke можно указывать методы, лямбда-выражения, а также массив делегатов типаAction.
