Является ли CWnd :: GetSafeHwnd () и CWnd :: m_hWnd ThreadSafe? - PullRequest
8 голосов
/ 17 февраля 2012

Я сталкиваюсь с многочисленными сбоями в приложении, которое является многопоточным.

Читая эти MSDN страницу , техническую заметку и в этой статье по TLS , я понял, что CWnd объекты отображаются в HWND в локальном потоке Storgae (TLS, доступ к памяти которого зависит от потоков).

Я собирался отделить все, что похоже на CWnd поток-удаленный доступ, и преобразовать его в HWND ссылки, а затем использовать ::PostMessage в качестве порта связи.

Но один из моих коллег действительно настоял на том, чтобы я просто оставил CWnd* в чужих потоках, принял политику ::PostMessage в порядке, но использовал CWnd::GetSafeHwnd() или pMyCWnd->m_hWnd во внешних потоках, чтобы восстановить родной HWND.

Я утверждал, что нигде Я видел, что GetSafeHwnd() является потокобезопасным, и что объект CWnd находится в TLS, его значение в другом потоке отличается.

Я не прав? В MSDN явно используется термин Неожиданные результаты .

Какова ваша точка зрения относительно вызова CWnd::GetSafehwnd() или pMyCWnd->m_hWnd во внешних потоках из потока создателя?

Есть ли у вас документация MSDN, в которой говорится, что это безопасно или нет.

Ответы [ 3 ]

10 голосов
/ 17 февраля 2012

CWnds не отображаются в HWND; HWND сопоставляются с CWnds, и это происходит для каждого потока. Объект CWnd не находится в TLS (как это будет работать?), Но временные объекты CWnd создаются для каждого потока.

Доступ к временному объекту CWnd из неправильного потока - определенно плохая идея (по причинам, описанным Марком Рэнсомом).

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

Если это вас беспокоит (потому что это явно не задокументировано), тогда просто сделайте копию HWND и дайте доступ к потокам.

P.S. Вот статья, на которую вы ссылались на английском языке.

5 голосов
/ 17 февраля 2012

GetSafeHwnd - это просто оболочка, которая проверяет, имеет ли this значение NULL, возвращает m_hWnd, если нет, и NULL, если это так. Он не будет более безопасным для потоков, чем m_hWnd.

Когда вы создаете временный CWnd *, MFC уничтожит его в точке, которую он считает безопасным, такой как следующий проход через цикл сообщений. Если у вас есть несколько потоков, использующих MFC, ваш временный объект может быть разрушен, пока вы все еще используете его. Ничто из того, что вы можете сделать из своей ветки, не обнаружит эту ошибку.

1 голос
/ 17 февраля 2012

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...