- •А.Ю. Быков
- •Быков Александр Юрьевич
- •Подхода
- •Оглавление
- •Введение
- •1. Лабораторная работа № 1. Изучение диалоговых окон и элементов управления в Win api
- •1.1. Цель и задачи работы, требования к результатам ее выполнения
- •1.2. Краткая характеристика объекта изучения
- •1.2.1. Классификация диалоговых окон
- •1.2.2. Окна сообщений
- •1.2.3. Создание модального диалогового окна
- •1.2.4. Элементы управления диалогового окна
- •Кнопка, контрольный переключатель, радио кнопка
- •Текстовое поле
- •Примеры
- •Примеры посылки сообщений списку
- •1.3. Задачи и порядок выполнения работы
- •Пример выполнения работы
- •1.4. Форма отчета по лабораторной работе
- •1.5. Вопросы для самоконтроля
- •2.1. Цель и задачи работы, требования к результатам ее выполнения
- •2.2. Краткая характеристика объекта изучения
- •2.2.1. Понятие класса и объекта
- •2.2.2. Доступность компонент класса
- •2.2.3. Основные элементы класса Компонентные данные и функции класса
- •Конструктор класса
- •Деструктор класса
- •2.3. Задачи и порядок выполнения работы
- •Пример выполнения работы
- •2.4. Форма отчета по лабораторной работе
- •2.5. Вопросы для самоконтроля
- •3.1. Цель и задачи работы, требования к результатам ее выполнения
- •3.2. Краткая характеристика объекта изучения
- •3.3. Задачи и порядок выполнения работы
- •Пример выполнения работы
- •3.4. Форма отчета по лабораторной работе
- •4.2.3. Особенности конструкторов при наследовании
- •4.2.4. Особенности деструкторов при наследовании
- •4.2.5. Переопределение функций. Виртуальные функции
- •4.3. Задачи и порядок выполнения работы
- •Пример выполнения работы
- •4.4. Форма отчета по лабораторной работе
- •5.3. Задачи и порядок выполнения работы
- •Пример выполнения работы
- •5.4. Форма отчета по лабораторной работе
- •6.2.2. Создание потока с помощью api – функций
- •6.2.3. Синхронизация потоков
- •1. Взаимное исключение.
- •3. Семафор
- •4. Событие
- •6.2.4. Синхронизация процессов
- •6.3. Задачи и порядок выполнения работы
- •Пример выполнения работы
- •6.4. Форма отчета по лабораторной работе
- •6.5. Вопросы для самоконтроля
- •7. Лабораторная работа № 7. Изучение библиотеки классов mfc
- •7.1. Цель и задачи работы, требования к результатам ее выполнения
- •7.2. Краткая характеристика объекта изучения
- •7.2.1. Обзор упрощенной иерархии классов библиотеки mfc
- •7.2.2. Состав простейшего приложения в mfc
- •7.2.3. Обработка сообщений в mfc
- •Некоторые функции обработчики
- •7.2.4. Вывод графики в mfc
- •Графические объекты
- •Добавление обработчиков сообщений и событий в однодокументном приложении
- •Вывод графики и перерисовка
- •7.3. Задачи и порядок выполнения работы
- •Пример выполнения работы
- •7.4. Форма отчета по лабораторной работе
- •7.5. Вопросы для самоконтроля
- •8. Лабораторная работа № 8. Изучение разработки приложений для платформы Microsoft .Net с использование библиотеки классов .Net Framework
- •8.1. Цель и задачи работы, требования к результатам ее выполнения
- •8.2. Краткая характеристика объекта изучения
- •8.2.1. Обзор платформы Microsoft .Net
- •8.2.2. Единая среда исполнения
- •8.2.4. Понятие управляемого кода
- •8.2.6. Система общих типов
- •8.2.7. Обзор библиотеки классов .Net Framework
- •8.2.8. Класс Form
- •8.2.9. Обработка событий
- •8.2.10. Основные элементы управления
- •8.4. Форма отчета по лабораторной работе
- •8.5. Вопросы для самоконтроля
- •Заключение
- •Рекомендуемые источники
- •Приложение а. Варианты заданий для выполнения лабораторных работ Варианты заданий для лабораторной работы № 1
- •Варианты заданий для лабораторной работы № 2
- •Варианты заданий для лабораторной работы № 3
- •Варианты заданий для лабораторной работы № 4
- •Варианты заданий для лабораторной работы № 5
- •Варианты заданий для лабораторной работы № 6
- •Часть I
- •Часть II
- •Варианты заданий для лабораторной работы № 7
- •Варианты заданий для лабораторной работы № 8
3. Семафор
Работает по аналогии с взаимным исключением, только доступ к объекту может получить не один поток, а их число определяется параметром MaximumCount (при занятии потоком семафора текущее значение счетчика уменьшается на 1, семафор полностью занят, если значение счетчика равно 0)
HANDLE CreateSemaphore( // Создать семафор
LPSECURITY_ATTRIBUTES lpAttr, // Атрибуты доступа
LONG InitialCount, // Начальное значение семафора
LONG MaximumCount, // Макс. значение
LPCTSTR lpName ); // Имя семафора
Возможная схема использования:
WaitForSingleObject(HSem, // Занять семафор
INFINITE); // ждите сколько нужно
Count++; // Работа с синхронизированным объектом
ReleaseSemaphore(HSem, 1, 0); // Освободить одно место семафора
4. Событие
Событие используется для того, чтобы один поток послал другому потоку, ожидающему наступление этого события, что событие произошло. Событием можно назначить любую точку в алгоритме программы, например, некоторая подзадача решена, т.е. получены необходимые результаты, являющиеся исходными данными для ожидающего события потока.
HANDLE hEvent;
hEvent=CreateEvent(0, // Создать объект - событие
false, // TRUE событие со сбросом вручную FALSE — событие с автосбросом
false, // свободное (TRUE) занятое (FALSE).
0);
WaitForSingleObject(hEvent,
INFINITE); // Программа далее не выполняется
Когда событие произошло необходимо вызвать в другом потоке функцию
SetEvent(hEvent);
6.2.4. Синхронизация процессов
С помощью объектов синхронизации можно организовать синхронизацию различных процессов. Например, доступ к объекту синхронизации, созданному в одном процессе (приложении), можно получить в другом приложении с помощью вызова функции OpenОбъект (Вместо термина объект идет имя объекта синхронизации). Например, для объекта «Событие» вызов имеет вид:
HANDLE OpenEvent(
DWORD dwDesiredAccess, // флаги доступа
BOOL bInheritHandle, // режим наследования
LPCTSTR lpName // имя события
);
Возможные значения флагов доступа:
EVENT_ALL_ACCESS
EVENT_MODIFY_STATE
SYNCHRONIZE
6.2.6. Создание потока в Си++ с помощью стандартной библиотеки C++
Поддержка многопоточности в языке Си++ определена стандартом 2011 г. [5], до этого приходилось использовать платформенно-зависимые средства, как представлено выше. В продуктах компании Microsoft можно пользоваться стандартными средствами библиотеки Си++ для создания потоков, начиная с версии Microsoft Visual C++ 2011. Для создания потока необходимо использовать класс thread [5], входящий в пространство имен std. Ниже представлен листинг программы с комментариями. Программа создана как консольное приложение. В программе в главном потоке (функция main) создаются два дочерних потока, в потоковую функцию в качестве параметра передается строка текста (объект класса string), это строка печатается 10 раз.
// stdafx.h: включаемый файл для стандартных системных включаемых файлов
// или включаемых файлов для конкретного проекта, которые часто используются, но
// не часто изменяются
//
#pragma once
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
// TODO: Установите здесь ссылки на дополнительные заголовки, требующиеся для программы
#include <string>
#include <iostream>
#include <thread>
using namespace std;
// Thread1.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
void myfun(string str) // Потоковая функция может иметь параметры при необходимости
{
for (int i = 0; i < 10; i++) // 10 раз печатаем строку
cout << endl << str.data();
}
int _tmain(int argc, _TCHAR* argv[])
{
thread th1(myfun, "Java"), th2(myfun, "C++");
// Создаем 2 объекта, первый параметр конструктора- указатель на потоковую функцию,
// следующие параметры передаются в потоковую функцию при необходимости
th1.join(); // Ждем завершение дочернего потока
th2.join(); // Ждем завершение дочернего потока
system("pause"); // Останавливаем программу до нажатия любой клавиши
return 0;
}
Результаты работы программы представлены на рисунке 4.

Рисунок 4 – Результаты работы многопоточной программы
На рисунке 4 в некоторых случаях виден беспорядочный вывод (каждая строка должна печататься с новой строчки, это правило иногда нарушено), что связано с отсутствием синхронизации (два потока работают одновременно с одним объектом cout).
Для синхронизации можно использовать объект класса mutex [5]. Ниже представлена программа с синхронизацией при печати.
// stdafx.h: включаемый файл для стандартных системных включаемых файлов
// или включаемых файлов для конкретного проекта, которые часто используются, но
// не часто изменяются
//
#pragma once
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
// TODO: Установите здесь ссылки на дополнительные заголовки, требующиеся для программы
#include <string>
#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
// Thread1.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
mutex mut; // Создаем объект для синхронизации
void myfun(string str) // Потоковая функция может иметь параметры при необходимости
{
for (int i = 0; i < 10; i++) // 10 раз печатаем строку
{
mut.lock(); // Блокируем объект
cout << endl << str.data();
mut.unlock(); // Снимаем блокировку
}
}
int _tmain(int argc, _TCHAR* argv[])
{
thread th1(myfun, "Java"), th2(myfun, "C++");
// Создаем 2 объекта, первый параметр конструктора- указатель на потоковую функцию,
// следующие параметры передаются в потоковую функцию при необходимости
th1.join(); // Ждем завершение дочернего потока
th2.join(); // Ждем завершение дочернего потока
system("pause"); // Останавливаем программу до нажатия любой клавиши
return 0;
}
Результаты работы программы с синхронизацией представлены на рисунке 5.

Рисунок 5 – Результаты работы многопоточной программы с синхронизацией
