Поделиться через


Многопоточность. Создание рабочих потоков

Рабочий поток широко применяется для обработки фоновых задач, что дает возможность без задержек продолжить работу с приложением. Примерами рабочих потоков являются такие задачи, как пересчет и фоновая печать. В данном разделе описываются шаги, которые необходимо выполнить для создания рабочего потока. Ниже приведен список разделов.

  • Запуск потока

  • Реализация функции управления

  • Пример

Создание рабочего потока является относительно простой задачей. Для запуска потока необходимо выполнить всего два шага: реализовать функцию управления и запустить поток. Создавать производный класс из CWinThread необязательно. Производный класс можно создать, если необходима специальная версия CWinThread, однако, для большинства простых рабочих потоков это не требуется. Можно использовать CWinThread без изменений.

Запуск потока

Существует две перегруженные версии AfxBeginThread: — это функция, которая может только создать рабочие потоки и одно, может создать и потоки и рабочие потоки интерфейса пользователя. Чтобы начать выполнение рабочего процесса с использованием первой перегрузки, вызовите AfxBeginThread, предоставив следующие сведения:

  • адрес функции управления;

  • параметр, передаваемый в функцию управления.

  • желаемый приоритет потока. (Необязательно) По умолчанию используется обычный приоритет. Дополнительные сведения о доступных уровнях приоритета см. в разделе SetThreadPriority в Windows SDK.

  • Желаемый размер стека для потока. (Необязательно) По умолчанию используется тот же размер стека, что и для создающего потока.

  • CREATE_SUSPENDED,если необходимо создать поток в состоянии приостановки. (Необязательно) Значением по умолчанию является "0", то есть поток запускается в обычном режиме.

  • (необязательно) Желаемые атрибуты безопасности. По умолчанию используются те же параметры доступа, что и для родительского потока. Дополнительные сведения о формате информации о безопасности см. в разделе SECURITY_ATTRIBUTES в Windows SDK.

AfxBeginThread создает и инициализирует объект CWinThread, запускает его и возвращает его адрес (для возможности дальнейших ссылок на объект). Для подтверждения того, что в случае возникновения ошибки освобождение выделяемой для всех объектов памяти осуществляется должным образом, во время создания выполняются специальные проверки.

Реализация функции управления

Функция управления определяет поток. При вводе этой функции поток запускается, а при ее действии поток завершается. Данная функция должна иметь следующий прототип:

UINT MyControllingFunction( LPVOID pParam );

Параметр является одиночным значением. Значение, которое эта функция получает в данном параметре, является значением, переданным в конструктор при создании объекта потока. Функция управления может интерпретировать это значение любым выбранным способом. Оно может обрабатываться как скалярное значение или указатель на структуру, содержащую многочисленные параметры, или может быть пропущено. Если параметр ссылается на структуру, ее можно использовать не только для передачи данных из вызывающего объекта в поток, но и для передачи данных из потока в вызывающий объект. При использовании такой структуры для передачи данных обратно в вызывающий объект, поток уведомляет вызывающего объекта, когда результаты готовы. Дополнительные сведения о связи рабочего потока с вызывающим объектом см. в разделе Многопоточность. Советы по программированию.

При завершении функции она должна вернуть значение UINT, указывающее на причину завершения. Обычно этот код выхода имеет значение "0", означающее успешное выполнение, или другие значения, означающие различные типы ошибок. Это полностью зависит от реализации. Некоторые потоки могут поддерживать счетчики объектов и возвращать текущее количество использования этого объекта. Сведения об извлечении приложениями данного значения см. в разделе Многопоточность. Завершение потоков.

Существуют некоторые ограничения в работе с многопоточными программами, написанными с помощью библиотеки MFC. Описание этих ограничений, а также другие советы по использованию потоков см. в разделе Многопоточность. Советы по программированию.

Пример функции управления

В следующем примере демонстрируется способ определения функции управления и ее использование из другой части программы.

UINT MyThreadProc( LPVOID pParam )
{
    CMyObject* pObject = (CMyObject*)pParam;

    if (pObject == NULL ||
        !pObject->IsKindOf(RUNTIME_CLASS(CMyObject)))
    return 1;   // if pObject is not valid

    // do something with 'pObject'

    return 0;   // thread completed successfully
}

// inside a different function in the program
.
.
.
pNewObject = new CMyObject;
AfxBeginThread(MyThreadProc, pNewObject);
.
.
.

Дополнительные сведения

См. также

Основные понятия

Реализация многопоточности на языке C++ с помощью классов MFC