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;
}

Обратная связь:
230360822 
ved-vampir@yandex.ru

Посетите мой проект:Портал вникуда
Портал вникуда

Визитная карточка эксперта RFpro.ru

 
Hosted by uCoz