Русскоязычный видео курс по основам языка C# и технологиям .NET. Рассматриваются
практические задачи реализации рефлексии и применения многопоточности
Рефлексия и многопоточность практические работы
Основы языка C# и платформы .NET.
Более 45 видеоуроков о реализации
расширяемых приложений и создании плагинов для них, создание многопоточного
приложения.
Плагины используются повсеместно.
Возьмите такие пакеты программ как Word, Photoshop и т.д. Они имеют способность
к расширению сторонними библиотеками, в том числе после того, как уже
установлены на вашей машине.
Это достигатеся за счет рефлексии -
отражения типов. Создание плагинов заключается в написании обычных библиотек
классов - dll.
Сегодня почти не встретить
приложения, работающего в одном потоке процесса. Но также часто можно встретить
зависающие приложения раз-за-разом, или в определенных местах работы приложения.
Это проблема не верно спроектированных нитей потоков. О создании поистине
многопоточного приложения мы и поговорим в данном курсе.

Серия видеокурсов по технологии .NET и языку C#.
Часть IV.
Рефлексия и многопоточность
http://skillcoding.com
Важным аккордом перед началом разработки реальных работающих в интернете
вебсайтов на ASP.NET-Ajax является полное арскрытие темы рефлексии и
многопоточности. Не стоит думать, что эти две составляющие технологии .NET
применяются только на клиентских приложениях. Рефлексия используется
повсеместно, а использование дополнительных потоков как нельзя кстати пригодится
в написании быстрых, отзывчивых и стойких к нагрузкам вебсайтов.
Поэтому, более нет уже надобности расписывать о преимуществах технологий,
понимающий поймет. Представляю курс:
ПРОФЕССИОНАЛЬНАЯ ПОДГОТОВКА РАЗРАБОТЧИКА
по языку C# на платформе .NET.
Часть
4 Рефлексия и многопоточность
Курс посвящен практическому применению возможностей рефлексии для построения
расширяемых приложений, создании плагинов, работе с атрибутами, а также
разработке многопоточных приложений.
Более 45 видео уроков о практической разработке проектов.
Изображения меню курса я не стану уже демонстрировать и саму DVD-коробку тоже. Это
ни к чему, важнее ознакомиться с содержанием обучающего материала.
Теперь рассмотрим, какие уроки включены в каждый раздел, и какие знания Вы получите,
изучив их.
Раздел 1
(Car Shop)
Создание расширяемого приложения автосалона по продаже автомобилей различных марок и моделей
Урок 1
- Понятие плагина на примере фотошоп
- Преимущества плагинов, масштабируемость приложения
- Недостатки плагинов, скорость обработки
- Создание dll для проекта автосалона
- Модель проекта автомагазина
- Поставщики моделей, модельный ряд. Общее для создания классов
- Расширяемое приложение с наименьшими усилиями за минимальное время
- Определение с классами (типами), интерфейсами и методами.
Урок 2
- Создание решения
- Создание пространства имен и файла для ключевых интерфейсов
- Создание интерфейса для марки машины
- Создание интерфейсов для моделей
- Создание класса проданых автомобилей
- Применение атрибутов для хранения значения названия марки машины
- Создание пользовательского атрибута и применение его к соответствующим классам
- Настройка проектов решения на хранение плагинов в отдельной папке
Урок 3
- Метод получения списка моделей для каждого класса - определение сигнатуры метода.
- Интерфейсный тип возвращаемого значения метода
- Создание открытого абстрактного класса марки машины, реализовывающего интерфейс модели
- Создание первых dll
- Создание dll-ок для марок и для модельного ряда. Кдасс Opel наследуется от абстрактного
- Связывание класса модельки с классом марки через атрибут
Урок 4
- Создание пользовательского интерфейса
- Кидаем на форму контролы ListBox и NumericUpDown и несколко Button
- Расставляем соответствующие обработчики события SelectedIndexChanged
Урок 5
- Необходимость загрузки dll-ок марок машин и их модельного ряда
- Создание соответствующих списков IList
- Создание и реализация метода загрузки всех марок автомобилей
- Необходимость выборки среди всех dll определенные под условием на основе рефлексии
- Получение папки исполнения программы AppDomain.CurrentDomain.BaseDirectory
- Список всех dll Directory.GetFiles
- Вытягивание из списка требуемых dll
- Assembly.LoadFile - загрузка сборки
- Проверка типов в сборке Assembly.GetTypes
- Анализ типа марки авто
- Получение типа Type.GetInterface
- Определение Type.IsAbstract
- Активируем объекты Interface instance = Activator.CreateInstance
- Заполнение ListBox первым объектом из dll
- Создание еще одного проекта сборки марки и также добавление её с помощью рефлексии в список элементов ListBox
Урок 6
- Реализация метода получения всех моделей для абстрактного класа
- Возвращение типа Ilist
- AppDomain.CurrentDomain.BaseDirectory, Directory.GetFiles
- Поиск и отбор всех моделей текущей марки авто
- Возможность искать по интерфейсу ICarModel
- Иной способ отбора dll по атрибутам
- Нахождение всех атрибутов типов текущей сборки и перебор их по одному
- Type.GetCustomAttributes - получаем все атрибуты типа в сборке
- Вытягивание и проверка пользовательского свойства на требуемое значение марки авто
- Нахождение типа интерфейса для создания экземпляра типа Type.GetInterface
- Activator.CreateInstance(Type)
- Добавление объекта в ListBox
Урок 7
- Получение всего модельного ряда текущей марки
- Преимущества применения полиморфизма на базе абстрактного класса
- Создание еще проектов для dll-ок моделей
- Проверка работоспособности приложения
Урок 8
- Получение списка цветов для конкретной модели
- Сброс всех выборов по всем ListBox
Урок 9
- Перенос деталей заказа на форму приема заказов
- Заполняем список заказов
- Формируем детали самого заказа
- Исправяем исключение "индекс за пределами диапазона"
- Почему данное тестовое задания не всегда и все выполняют до конца и при этом получают работу
Урок 10
- Реализация функциональности выполнения заказа
Урок 11
- Анекдот из жизни
- Последние штрихи по функциональности - очистка ListBox и вывод информации о проданных авто
- Отработка кода
Урок 12
- Расстановка точек останова для просмотра работы рефлексии в действии
- Использование отладчика для слежением за присутствующими dll и за теми, которые отбираются в процессе выполнения скрипта по шагам
Урок 13
- Создание плагина для ноаого поставщика автомобилей
- Демонстрация простейшего подключения плагина в приложение
Перейти к форме заказа
Раздел 2
(теория по потокам и процессам)
Синхронизация потоков, процессов, передача данных между процессами
Урок 1
- Обзор понятийного апарата многопоточности
- Понятие потока с точки зрения режима выполнения приложения
- Синаксис создания потоков
- Создание двух потоков и запуск в них соответствующих методов
- Анализ работы многопотокового приложения
- Неравномерный вывод результатов работы методов в различных потоках
- Потоки и процессы - пару слов для начала
- Два потока - один метод
- Выводы по поводу прошлого примера
- Сколько стеков может быть в программе (в приложении)?
- Локальные переменные метода в потоках
- Выделение отдельного стека для локальной переменной
- Один объект и вызов его метода в разных потоках
- Выносим переменную на уровень класса
- Анализ измененных результатов работы программы
- Потоки и переменные уровня класса
- Потоки связаны с методами, а не данными, но методы связаны с данными
Урок 2
- Статические и объектные поля
- Причина неприятностей в псевдопаралельности
- 10 раз запускаем программу и наблюдаем 8 раз один результат, 2 раз иной
- Анализ такого поведения
- Роль Clr в жизни и работе потоков
- Итоги многопоточности: планировщик потоков, время выполнения потока, блокировка потока, ресурсы машины, один процессор, несколько процессоров, роль операционной системы
Урок 3
- Процесс - что же это такое, определение процесса
- В чем же различие потоков и процессов, что общего
- Управляемая куча для потоков и для процессов
- Процесс, приложение, потоки
- Общение потоков, общение процессов
- Исключение в методе оптока
- Попытка применения конструкции try catch
- Правила вылова исключений в потоках - стек вызовов
Урок 4
- Применяем метод Join для продления времени работы потока
- Более верный вариант решения проблемы через оператор lock
- Почему лочатся блоки кода только при помощи ссылочного объекта, но не простого типа?
- Метод Sleep применять следует только для приостановки потоков
- Основные и фоновые потоки, когда какие использовать?
- Пример работы с фоновыми потоками
- Бесконечные циклы не есть проблема в фоновых потоках
- Приоритетность потоков ThreadPriority
- Что же дает приоритетность? Чего приоритеность не может дать для потоков?
- Diagnostics.Process.GetCurrentProcess - получение текущего процесса. PriorityClass свойство для процесса
- ProcessPriorityClass.RealTime - лучше не юзать!!!
- Процессы изолированы? Насколько?
Урок 5
- Как получать процессы на машине и как их убивать
- Получаем в массив список работающих в данный момент процессов
- Выводм на экран список процессов
- Выборочно убиваем процессы
- Права пользователя для закрытия процесса Process.Kill и WaitForExit
- Пробуем на c# выгрузить Skype
- Правила применения оператора lock
- Рекурсия и lock - очень плохая идея, очень
- Лочить следует только минимальный объем кода
- Гонка потоков - условие зависимости
- Роль CLR в гонке потоков
- Наглядный пример управления CLR множеством потоков приложения
Урок 6
- Метод Abort для остановки потока
- Остановленные потоки, приостановленные, в ожидании
- Когда допустимо использовать метод Abort для остановки метода потока?
- Неуправляемый код в потоке
- Какое количество потоков может быть запущено в одном приложении?
Урок 7
- Класс AutoResetEvent
- Управление временем доступа к объекту некоторого потока
- Пример использования объекта AutoResetEvent
- Объект типа EventWaitHandle
- Метод ожидания WaitOne и метод сигнала Set
Урок 8
- Механизм общения между процессами
- Создание нескольких приложений для демонстрации процесса передачи/приема данных от одного к другому
- Имя системного события синхронизации конструктора EventWaitHandle
- Свойство EventWaitMode.AutoReset
- Получение дескриптора исгнала из первого приложения
- EventWaitHandle.OpenExisting
- Обработка ексепшена - обязательное условие при отправке сообщения
- Проверка работы двух приложений общения между собой
Урок 9
- Windows Forms проект отправки сообщения
- Пространства имен System.Security.AccessControl и Security.Principal
- Типы EventWaitHandleRights, EventWaitHandleSecurity, SecurityIdentifier, WellKnownSidType, EventWaitHandleAccessRule
- Метод AddAccessRule для создание прав доступа
- Перечисление EventResetMode
- Получение приложением консоли сигнала процесса Windows Forms приложения
Урок 10
- Наличие полей уровня класса. Компилятор помещает поле в регистр
- Проблема оптимизации кода компилятором при использовании несокльких потоков доступа к общему полю
- Повторное использование потока для многократного запуска метода в отдельных потоках
- Правильная синхронизация единственного потока при повторных использованиях
- Ключнвое слово volatile
- Созднае целевого метода для запуска в потоках
- Загрузка потока методами несколько раз
Урок 11
- Ограничение количества одновременно работающих с объектом потоков Semaphore
- 5 потоков в ожидании и 3 потока в действии семафора
- Выпадение потоков из семафора
- Необходимость указания конструкции lock, или оператора volatile
- lock - частный случай Semaphore
Перейти к форме заказа
Раздел 3
(Food Market)
Разработка многопоточного эмулятора работы продуктового супермаркета
Урок 1
- Постановка задачи работы супермаркета
- Пояснение модели работы супермаркета
- Управляющий сетью магазинов, супермаркет, менеджер, стенды, продавцы, покупатели, очередт
- Выяснение вопроса прожаж на макимально возможные прибыли
- Структура перемещения посетителя по стендам, продавцам и проход через менеджера
- Модель создания сущностей с точки зрения кода c#
- Момент открытия магазина через создание иерархий конструкторов сущностей по класса типов
- Определение динамической формулы на мгновенное вычисление рентабельности стенда
- Почему рентабельность стенда постоянно меняется
- Нормальный режим работы магазина
- Режим открытия магазина
- Режим закрытия магазина и перемещение по магазину уже прибывших посетителей
- Режим полного закрытия магазина.
Урок 2
- Создание консольного приложения для проекта супермаркета
- Почему выбираем именно консольное приложение?
- Многопоточность на практике
- Добавление в решение нового проекта
- Решение для сети магазинов и решение для нашего конкретного супермаркета
- Создание библиотеки классов
- Создание типов магазина, менеджера, стенда, продавца и покупателя
- Установка ссылки на проект магазина
- Создание инструкций получения команды к открытию магазина
- Создание инструкций получения команды на закрытие магазина
- Создание потока для работы всего магазина
- Создание метода открытия магазина
- Создание метода для закрытия магазина
- Магазин не может сам закрыться мгновенно
Урок 3
- Развитие класса покупателя
- Список коллекция Dictionary, List посещенных стендов
- Почему используем List<string> для списка посещенных стендов, а не пользовательский тип?
- Создание свойства для списка стендов
- Уникальный номер покупателя
- Лучше хранить id стендов, а названия стендов хранить в app.config
- Создание прегрузки конструктора
- Наполнение типа стенда
- Создание поля рентабельности типа decimal и его свойства
- Количество проданных товаров со стенда
- Название продукта и цена продукта стенда
- Обобщенный список продавцов стенда List<T>
- Очередь покупателей на стенде - Queue<T>
- Создание соответствующих свойств для открытия чтения полей
- Прегрузка конструктора для типа стенда
- Обнуление всех счетчиков объекта класа стенд
- Список продавцов повешен на генератор случайных чисел
Урок 4
- Класс магазина, счетчик посещений магазина
- Объект менеджера
- Создание делегата delegate NewVisitor для события появления нового посетителя
- Создание события посещения магазина новым покупателем
- Отдельный поток Threading.Thread для работы менеджера в новом потоке
- Состояние магазина - перечисление enum
- Потребность передачи ссылки на магазин в объект менеджера
- Метод для запуска менеджера к работе
- Реализация метода открытия магазина
- Переключение состояния магазина
- Запуск метода старта роботы менеджера в отдельном потоке Thread.Start();
- Бесконечный цикл для ожидания новых посетителей на входе объекта магазина
- Условие в цикле while для ожидания новых посетителей
- Генерация события появления нового посетителя. Установка задержки потока
- Наполнение метода закрытия магазина
- Переключение состояние магазина с вызовом метода менеджера к началу завершения работы
- Последовательность вызовов потоков - влияние различных потоков на общие свойства объектов класса
- Один объект - вызов отдельных методов одновременно в разных потоках
Урок 5
- От какой сущности стенд должен принимать покупателей, от менеджера, или из очереди
- В какой способ стенд будет получать покупателя - через событие, или просто вызовом метода напрямую, или присваивание из вне текущего посетителя?
- Выбор способа принятия покупателя
- Перечисление enum для хранения состояния стенда
- Создание делегата delegate для события завершения работы стенда
- Создание делегата для события возврата покупателя обратно во внешнюю среду
- Иерархия поступления команд на начало работы и на завершение работы, на полное прекращение работы
- Что использовать, аналогию из Ajax для постоянного опрашивания, или все-таки ожидать конкретного события для мониторинга состояния дочерних объектов
- Создание делегата delegate для события полного завершения работы стенда
- Метод начала работы стенда
- Метод завершения работы стенда
Урок 6
- Организация работы продавца
- Доступ продавца к очереди покупателей
- Проблема одновременного доступа к очереди покупателей менеджером, стендом и продавцом
- Стенд берет первого покупателя из очереди и отдает свободному продавцу на стенде. Приняв покупателя передает назад менеджеру
- Иерархия вызовов обработчиков событий сущностей в связке над очередью
- Состояние продавца: работает; не работате; работает, но совбодный
- Создание события для завершения продажи товара покупателю
- Создание конструктора для продавца
- bool свойство, демонстрирующее загруженность продавца
- Метод принятия нового покупателя для обработки на стенде
- Метод для полного прекращения работы продавца
- Метод для начала работы продавцов
- Эмуляция постоянной работы сущности - применение потока для постоянного выполнения цикла метода
- Сколько сущностей, - столько и потоков
- Продавец работает с множеством покупателей
- Как определить, что продавец занят покупателем
- Что передавать продавцу: ссылку на покупателя, сам объект покупателя?
- Эмулирование процесса выполнение покупки покупателем товара на стенед
- Возврат покупателя обратно к началу стенда через генерацию события
Урок 7
- Реализация класса менеджера
- Перечисление enum для состояния менеджера
- Создание списка потоков для стендов List<Thread>
- Свойство текущего покупателя для менеджера
- Список стендов List<T>
- Делегат delegate для события полного освобождения менеджера
- Событие Event полного прекращения работы менеджера
- decimal общая прибыль по всем стендам
- Количество покупателей, посетивших все стенды
- List<int>, или List<Buyer>?
Урок 8
- Конструктор для менеджера
- Обнуление прибыли, покупателей со всех стендов, ...
- Создание списка стендов с продукцией List<string>, или List<Stend>
- app.config - необходимость хранения настроек приложения
- Загоняем стенды в потоки
- Подписка менеджера на событие выхода покупателя со стенад для всех стендов
- Создание метода-обработчика события появления нового покупателя у менеджера
- Обработчик события полного прекращения работы стенда
Урок 9
- Создание списка потоков для всех продавцов на каждом стенде
- Запуск потоков в цикле
- Массовая подписка на событие возврата продавцом покупателя
- Стенд содержит продавца, но продавец не содержит стенда
- Формула вычисления рентабельности каждого стенда6
- Абсолютная и относительная рентабельность стенда
- Реализация обработчика события возврата покупателя от продавца
- Мгновенная переправка покупателя менеджеру через генерирование события
- Наполнение информации покупателю о посещенных стендах покупателем
Урок 10
- Как быть, когда магазин закрывается и очереди к стенду нет, а продавцы заняты?
- Моент, когда следует полностью закрыть стенд с продавцами. Роль опросов менеджера
- Для стенда реализовываем метод определения свободны ли все продавцы
- Как отправлять покупателя на самый рентабельный стенд. Определение максимально рентабельного стенда
- Интерфейс IComparible для реализации в классе Stend для возможности сортировки стендов по рентабельности
- Метод начала работы стенда. Перевод стенда в новое состояние
- foreach для запуска потоков прдавцов
- Стенд может получать покупателя из очереди, отдавать покупателя продавцу, принимать покупателя от продавца и отдавать покупателя менеджеру
- Queue.Count для проверки есть ли очередь
- Queue.Dequeue() - для выборки первого посетителя из очереди
- Логика определения времени передачи покупателя из очереди к продавцу
- Условия определения режима работы с покупателями при разных состояних работы стенда
- Лучший момент проверки свободны ли все продавцы на стенде
- Команда продавцу закончить работу
- Генрация события полного прекращения работы конкретным стендом
Урок 11
- Метод запуска менеджера в работу
- В какой способ дать команду всем стендам начать работу
- Первая проверка на условие закрывающегося магазина
- Еще один бесконечный цикл для менеджера
- Thread.Sleep(50) - самое оно
- Метод для завершения работы всех стендов
- Метод появления нового покупателя то ли с входа магазина, то ли со стенда
- Обязательное условие проверки наличия объекта в текущей ссылке - свойстве посетителя
- Ожидание освобождения объекта через цикл while - самый неуклюжий способ!
- Еще раз по шагам проходим метод работы менеджера
- Сортировка стендов по рентабельности List<T>.Sort().Reverse()
- Три вида покупателя: новый, посетивший несколько стендов и посетивший все стенды
- Определение судьбы пришедшего посетителя
Урок 12
- Продолжение развития класса менеджера
- Обработчик события завершения стендом работы
- Проверка всех стендов на факт завершения ими работы
- Почему если в цикле foreach мы находим стенд с незавершенной работой мы вызываем return?!
- Место и время для генерации события полного прекращения работы менеджера
- Получение первой ошибки в работе приложения - зависание приложения в зацикленном потоке
- Ищем место зацикливания
- Пропустили переключатель режима работы менеджера
- Проблема отсутствия подписки в магазине на событие завершения работы менеджера
- Подписка на событие и реализация полного закрытия магазина
- Анализ существующего окда на предмет зацикливания
Урок 13
- Необходимость тестить без включенной Camtasia Studio что б не преключаться на процесс камтазии и её множества потоков
- Почему на одном из сетндов очередь к нему оказалась пуста - вылетело исключение Exception. Коварная ошибка при казалось бы 100% верном коде
- Дополнительное условие проверки количества покупателей в очереди к стенду
- Проблема одновременного доступа из многих потоков к очереди к стенду
- lock для свойства очереди
- Помещение всех небезопасных в отношении потоков свойств типовых объектов в конструкцию lock
- Необходимость ведения логов
Урок 14
- Вывод на консоль всей информации о перемещении покупателей по магазину
- Расстановка Console.WriteLine() в каждом углу кода проекта
- Случайно обнаруженная фатальная ошибка в коде, дающая торможение всех потоков
- Конструкция избавления менеджера от покупателя
- Введение дополнительных переменных для выведения на консоль детальной информации о текущей операции
- Метод появления нового покупатела - необходимость определения откуда пришел покупатель
- Проблема вывода покупателей, прошедших все стенды
Урок 15
- Внедрение консольного логирования в классе магазина
- Логирование в классе стенда
- Логирование в классе продавца
- Тестирование логирования на консоле
- Проблема обратного вывода логов по отношению к очередности вызовов инструкций кода - в чем дело
- Менеджер бстрее получает покупателя со стенда прежде чем стенд отдал покупателя менеджеру
- Аналогичная проблема - стенд принимает покупателя от продавца прежде чем продавец отдает покупателя стенду
Урок 16
- Выявление новых ошибок
- Exception по поводу, что очередь Queue пуста (метод работы менеджера)
- Опять причина во вмешивании в блок инструкций иного потока
- Проблема в работе Random
- Меняем список посетителей с List<int> на List<Buyer>
- Анализируем почему все стенды может пройти 7-й посетитель, а 5-й не успел?
Урок 17
- Исправление обратных вызовов в передаче покупателя сотрудниками магазина
- Вопросы к методу появления нового покупателя
- Глубокий анализ работы множества потоков по отношению к одной общей переменной. Проблемы, порождаемые этим обстоятельством в нашем приложении
- Отдельный обработчик для каждого стенда? 0 гибкости и 0 целесообразности
- Лочить все тело метода-обработчика?
- Альтернатива - замена одиночной переменно поля текущего покупателя на целую очередь покупателей - снятие целого вороха проблем и в 3 раза уменьшение объема и сложности кода
- Возможность применения класса Semaphor для ограничения количества одновременно доступных потоков, установленного в 1
Урок 18
- Проблема переключения потоков при установке цвета текста консоли
- Возложение надежды на lock. Оправдано ли?!
- Почему тело блока lock прерывается???
- Устранение последних прерываний для стендов
- Необходимость выполнения нескольких инструкций атомарно
Урок 18
- Внедряем логирование в проект
- Требования к ведению логов
- Отсутствие гибкости в логировании на консоле
- Вывод логов в базу данных?
- Вывод логов файл: в txt, или xml?
- Использование сторонней библиотеки модуля log4net
- Унимерсальность модуля log4net
- Аппендеры и фильтры в log4net
- Самому вести логи очень проблематично, ведь надо подкручивать Semaphor для одновременнй записи логов в один файл разными потоками
- Снятие великого множества проблем с помощью log4net
- Распаковывание исходников log4net в струтуру проекта
- Подключение ссылки на log4net.dll
- Добавление файла настроек приложения app.config
- Регистрация секции section name="log4net" type=
- Добавление аппендеров appender name="FileAppender" param
- Что означает аппендер, appender
- Почему прикрутили log4net и установили ссылки на dll, но компилятор говорит, что не найдены сборки
- log4net.Config.XmlConfigurator.Configure();
- Сообщение компилятора: "Не удалось найти имя типа или пространства имен "Log4net" (пропущена директива using или ссылка на сборку?)"
- Элемент "log4net" не существует в текущем контексте
- В чем причина не приятия требуемой dll-ки в проекте?
- Настройка проекта через app.config
- Создание объекта log4net типа ILog
- Исследование интерфейса ILog
- Метод InfoFormat для ведения логов
- LogManager.GetLogger(typeof(T)), какой тип указывать в качестве T?
- Тестирование ведения первой записи логов
- log4net определяет потоки для наполнения данными файл
Урок 18
- Добавление в ключевые участки кода программы вызовы метода InfoFormat для форматированного вывода дополнительной информации
- Небольшие отличия вывода информации в логи и на консоль
- Дополнительное назначение имен потокам для определения их переключения анализируя логи
- Получение первых ошибок логирования, ура!
- log4net:WARN StringFormat: Exception while rendering format
- Ошибка null обекта
- Еще не записали логи, а уже столько ошибок понаходили!
- Повышение скорости работы приложения говорит об отсутствии возникновения ошибок
- Еще один NullRefereceException в менеджере
- Определение причины назойливой ошибки
Урок 18
- Проблема в том,что менеджер не всегда удерживает посетителя
- Соотношения временных задержек потоков менеджера и стендов
- Чем меньше стендов, тем больше шансов получить ошибку
- Разбор полетов по записям в сгенерированном текстовом файле логов
- Проход по пути следования конкретного покупателя
Перейти к форме заказа

ВНИМАНИЕ!
С технической стороны доставки курса, - я по-прежнему несу всю ответственность по доставке данного диска. Это означает, что даже если диск не дойдет до Вас, либо придет в непригодном к использованию состоянии, я вышлю его повторно за свой счет. Пока клиент не получил заказанный курс, он (заказ) находится на особом положении в моей системе учета заказами.
Цена курса составляет:
$25,00
за DVD диски
или
10$ за электронные файлы
Доставка в любую страну мира включена в цену *
Перейти на страницу часто задаваемых вопросов
Форма заказа
Курс записан на DVD-диск. После получения Вашего
заказа диск отправляется на Ваш адрес ценной посылкой в специально
защищенной упаковке. Время оформления и отправки заказа –
не более
48 часов с момента его поступления в любой день недели **.
Только для граждан Украины возможна оплата наложенным платежом
в ближайшем почтовом отделении при непосредственном получении посылки на руки.
Чтобы начать оформление заказа, нажмите кнопку "Начать
оформление заказа". Если вы сомневаетесь в надежности автоматической оплаты
на данном сайте, Вы можете написать мне на aleksandergudok@gmail.com о желании приобрести курс.
Оплата производится либо онлайн (на один из кошельков: WMID 188371837698), либо офлайн.
В день отправки курса, по требованию клиента я предоставляю код бандероли, по которому возможно в режиме онлайн отслеживать за перемещением бандероли.
(!) Если у Вас возникли
проблемы с оплатой, или Вы хотите оплатить курс иным
образом, то напишите мне об этом на
aleksandergudok@gmail.com.
Если Вы ещё сомневаетесь дойдёт ли диск, то заверяю Вас, что дойдёт обязательно. В любом случае диск будет у Вас в руках!!!
* - в страны дальнего зарубежья возможна доставка быстрой авиа-почтой, которая на 3$ дороже обычной.
** - в зависимости от удалённости вашего населённого пункта, а также прочих условий, доставка посылки займет от 2 до 35 дней.
Если Вы проживаете в Украине, или просто имеете возможность посетить Винницу, то Вы можете лично встретиться со мной для мгновенного получения DVD-курса.