Priorities
Скачать cpp-файлы...
Скачать проект целиком...
Краткое описание программы:
Исследовательская задача. Цель - посмотреть, какое значение примет счётчик, инкременирующийся определённое количество секунд, в зависимости от приоритета потока. В задаче создаётся 5 потоков с разными приоритетами, количество секунд задаётся в главном окне с клавиатуры. Результаты выводятся в ListBox.
Затрагиваемые темы: создание приостановленных (suspended) потоков, присвоение приоритета потоку, запуск работы потока. (Дополнительно - отправка сообщений из потока главному окну программы.)
Описание используемых функций:
CreateThread
Эта функция создаёт поток внутри адресного пространства текущего процесса. Возвращает описатель созданного потока. Функция полезна, когда, например, нужно выполнять какие-то действия в оконном приложении, но не отключать при этом его интерфейс. В общем случае поток начинает работу сразу после вызова этой функции, и все действия, которые он выполняет, не мешают работе программы.
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes, //Аттрибуты защиты
SIZE_T dwStackSize, //Размер стека потока (если указать 0, то берётся по умолчанию)
LPTHREAD_START_ROUTINE lpStartAddress, //Адрес стартовой функции
LPVOID lpParameter, //Параметр для передачи потоку
DWORD dwCreationFlags, //Служебные флаги
LPDWORD lpThreadId //ID потока
);
Рассмотрим подробнее некоторые параметры функции:
lpStartAddress - указатель на стартовую функцию потока (т.е. её название), которую надо объявить внутри приложения. Она должна иметь определённый вид:
DWORD WINAPI ThreadProc( //Имя функции может быть произвольным
LPVOID lpParameter
);
lpParameter - параметр, передаваемый в стартовую функцию потока. Если потоку необходимо передать несколько параметров, следует либо использовать глобальные переменные, либо объявлять структуру со всеми необходимыми данными и передавать её.
dwCreationFlags - в основном этот параметр используется для того, чтобы обозначить, следует ли запустить поток сразу после создания или по вызову функции ResumeThread (в первом случае в параметре можно передать 0, во втором - флаг CREATE_SUSPENDED).
lpThreadId - возвращаемый параметр - id потока, который иногда может быть полезен (например, если потоку будет посылаться сообщение). Если id не нужен, можно передать NULL.
Более подробную информацию можно получить в MSDN.
Как используется в данной программе:
DWORD dwThreadId;
for (int i=0; i<5; i++)
{
pHandles[i]= CreateThread (NULL, 0, MyThread, NULL, CREATE_SUSPENDED, &dwThreadId);
//Создаём потоки в приостановленном состоянии (флаг CREATE_SUSPENDED)
SetThreadPriority(pHandles[i], pPriorities[i]); //Устанавливаем приоритет для него
}
for (int i=0; i<5; i++)
{
ResumeThread(pHandles[i]); //Запускаем работу потока
CloseHandle (pHandles[i]); //Закрываем описатель потока - он больше не нужен
}
В этом примере также используется функция SetThreadPriority:
Эта функция позволяет установить приоритет для потока.
BOOL SetThreadPriority(
HANDLE hThread, //Описатель потока
int nPriority //Приоритет
);
В качестве приоритета можно устанавливать одну из следующих констант: THREAD_PRIORITY_ABOVE_NORMAL, THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_IDLE, THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_TIME_CRITICAL.
Более подробную информацию можно посмотреть в MSDN.
PostMessage
Функция посылает сообщение заданному окну асинхронно, т.е. она возвращает управление сразу же (не дожидаясь, пока сообщение будет обработано). У окна, которому посылается сообщение, должен быть соответствующий обработчик, а идентификатор сообщения должен быть объявлен в программе.
BOOL PostMessage(
HWND hWnd, //HWND окна
UINT Msg, //Идентификатор сообщения
WPARAM wParam, //Параметр, передаваемый в обработчик
LPARAM lParam //Параметр, передаваемый в обработчик
);
Рассмотрим подробнее некоторые параметры функции:
hWnd - HWND окна, которому посылается сообщение. Это значение можно полусить из класса окна - оно хранится в поле m_hWnd.
Msg - идентификатор сообщения, если сообщение пользовательское, то надо объявить этот идентификатор при помощи директивы define (значения должны начинаться с WM_USER).
wParam, lParam - параметры, которые будут переданы в функцию-обработчик сообщения. В общем случае собственное сообщение можно добавить в карту сообщений и связать с ним определённую функцию-обработчик вида:
LRESULT MessageProc (
WPARAM wParam,
LPARAM lParam
);
Более подробную информацию можно получить в MSDN.
Как используется в данной программе:
#define WM_FINISH (WM_USER+1)
//...
BEGIN_MESSAGE_MAP(CPrioritiesDlg, CDialog)
//...
ON_MESSAGE(WM_FINISH, OnThreadFinish) //Добавляем своё сообщение в карту сообщений
END_MESSAGE_MAP()
//...
PostMessage(g_hWnd, WM_FINISH, (WPARAM)iCounter, (LPARAM)GetThreadPriority(GetCurrentThread()));
//...
LRESULT CPrioritiesDlg::OnThreadFinish(WPARAM wParam, LPARAM lParam)
//Функция-обработчик сообщения (объявлена в классе окна в h-файле)
{
//...
return 0;
} |