Многопоточность. Советы по программированию

При доступе к данным многопоточные приложения требуют больше внимания, чем однопоточные.Так как приложения являются многопоточными, одновременно выполняется несколько потоков, и следовательно, либо алгоритмы, либо данные, либо и те и другие должны знать, что данные могут одновременно использоваться более чем одним потоком.В данном разделе описаны способы предотвращения потенциальных проблем, возникающих при программировании многопоточных приложений с библиотекой Microsoft Foundation Class (MFC).

  • Доступ к объектам из нескольких потоков

  • Доступ к объектам MFC из потоков, не относящихся к MFC

  • Сопоставление дескрипторов Windows

  • Взаимодействие между потоками

Доступ к объектам из нескольких потоков

В связи с размером и производительностью объекты MFC не являются потокобезопасными на уровне объекта, а являются таковыми только на уровне класса.Это означает, что два отдельных потока могут управлять двумя различными объектами CString, а управление одним объектом CString двумя потоками невозможно.Если для управления одним объектом требуется использовать несколько потоков, то необходимо защитить доступ соответствующими механизмами синхронизации Win32, например, критическими секциями.Дополнительные сведения о критических секциях и других связанных объектах см. в разделе Синхронизация в Windows SDK.

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

Доступ к объектам MFC из потоков, не относящихся к MFC

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

Сопоставление дескрипторов Windows

Как правило, поток может получить доступ только к созданным им объектам MFC.По этой причине временное и постоянное сопоставление дескрипторов Windows сохраняется в локальном хранилище потока, помогающем реализовать защиту от одновременного доступа нескольких потоков.Например, рабочий поток не может выполнить расчет и затем вызвать функцию-член документа UpdateAllViews для окон, которые содержат новые измененные данные.Данное действие не произведет никакого эффекта, потому что сопоставление от объектов CWnd объектам HWND является локальным для первичного потока.Это означает, что один поток может сопоставить дескриптор Windows объекту С++, но другой поток может сопоставить тот же дескриптор различным объектам C++.Изменения, сделанные в одном потоке, не будут отражаться в другом потоке.

Несколько путей решения данной проблемы.Первый заключается в передаче в рабочий поток отдельных дескрипторов (например HWND), а не объектов С++.Затем рабочий поток добавит данные объекты во временное сопоставление, вызывая соответствующую функцию-член FromHandle.Можно также добавить объект в постоянное сопоставление потока, вызывая Attach, но только при условии гарантии того, что объект будет существовать дольше, чем поток.

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

Дополнительные сведения о сопоставлении дескрипторов см. в разделе Технические замечания 3.Дополнительные сведения о локальном хранилище потока см. в разделе Локальное хранилище потока и Использование локального хранилища потока в Windows SDK.

Взаимодействие между потоками

MFC предоставляет несколько классов, которые позволяют потокам синхронизировать доступ к объектам для обеспечения безопасности потока.Использование данных классов описано в Многопоточность. Использование классов синхронизации и Многопоточность. Случаи использования классов синхронизации.Дополнительные сведения об этих объектах см. в разделе Синхронизация в Windows SDK.

См. также

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

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