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

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

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

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

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

  • Адрес управляемой функции.

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

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

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

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

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

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