Многопоточность: Советы программирования MFC

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

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

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

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

Доступ к объектам MFC из потоков, отличных от MFC

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

Карты дескриптор Windows

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

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

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

Дополнительные сведения о картах дескрипторов см . в техническом примечание 3. Дополнительные сведения о локальном хранилище потоков см. в статье "Локальный поток" служба хранилища и использование локальных служба хранилища потока в пакете SDK для Windows.

Обмен данными между потоками

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

См. также

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