Создайте GUI-приложение на базе QMainWindow.
Для запуска потоков достаточно создать набор кнопок (кроме обычных PushButton, для задания приоритетов потоков возможно, понадобятся еще кнопки-переключатели - RadioButton), а всю оставшуюся клиентскую область окна предоставить для демонстрации взаимодействия потоков.
Каждый поток будет «рисовать» точки:
· своим цветом
· на своем уровне в окне (координата “y” будет у каждого потока своя)
· все потоки будут использовать (разделять) общую координату “x” для того, чтобы было видно, как ОС переключает потоки
Чтобы что-нибудь подобное можно было бы нарисовать в потоковой функции, ей нужно передать довольно много параметров, поэтому логично в качестве параметра передавать указатель на объект Вашего класса или структуры, в который можно запаковать все необходимые данные.
class MyData
{
HWND hw; //дескриптор окна (для того, чтобы окну можно было посылать сообщения из потоковой функции)
int y; //индивидуальная для потока координата Y
QColor col; //индивидуальный цвет
int maxX; // «докуда» рисовать
HANDLE hObject; //дескриптор синхронизирующего объекта
…
};
Подсказка: как можно/нужно формировать данные для передачи в потоковую функцию?
Так как рисуемые потоками точки будут разного цвета, с разными координатами – создаем вспомогательный класс MyPoint:
Данные:
=>
1. В классе MainWindow предусмотреть переменную для приема/хранения данных – контейнер, например static QVector<MyPoint> vPoints; . Почему лучше static???
2. Если потоковая функция является статическим методом класса, то имеет доступ ко всем статическим данным класса => в потоковой функции:
3. Чтобы из потоковой функции вызвать перерисовку окна:
вызвать перерисовку окна
, в котором нарисуйте все точки контейнера vPoints
Требуется запустить несколько потока с одинаковым приоритетом и «увидеть» как операционная система переключает потоки в соответствии с отведенными каждому потоку квантами времени.
Запуск потоков – системная Win32 API функция CreateThread ()
HANDLE CreateThread(//возвращаемое значение==0 - ошибка
LPSECURITY_ATTRIBUTES lpsa, // 0- защита по умолчанию и дочерние процессы не наследуют данный поток
SIZE_T cbStack, // размер стека или 0 (по умолчанию)
LPTHREAD_START_ROUTINE lpStartAddr, // указатель на функцию (точку входа) потока - DWORD WINAPI ThreadF(LPVOID lpvThreadParm); Не может быть NULL! Каждый поток внутри родительского процесса начинает свое выполнение с вызова специальной функции, называемой потоковой функцией. Выполнение потока продолжается до тех пор, пока не завершится его потоковая функция.
LPVOID lpvThreadParm, // значение или указатель на любые данные. Используется по замыслу программиста. Эти данные должны гарантированно существовать пока их использует потоковая функция, так как стек у каждого потока свой!!!
DWORD fdwCreate, // дополнительные флаги создания: 0 (начинает выполняться немедленно) CREATE_SUSPENDED - поток создается “остановленным”, то есть ожидающим запуска. Для того чтобы запустить такой поток, кто-то должен вызвать функцию ResumeThread()
LPDWORD lpIDThread// сюда функция вернет идентификатор (в NT – если Вам не нужно значение, можно передать 0)
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.