Chamadas recursivas para funções do Gestor de janela poderão falhar inesperadamente

Aplica-se a: Windows

Sintomas


Chamadas recursivas para funções de Gestor de janela exportadas por USER32. DLL poderá devolver sem efectuar a operação pedida e sem definir um código de erro. Isto ocorre normalmente em aplicações com uma hierarquia de janela profundamente aninhadas. Entre os sintomas poderá detectar:
  • Aplicações com uma hierarquia de janela profundamente aninhadas falhar redimensionar as janelas subordinadas correctamente quando a janela de moldura é redimensionada. Windows forem movidos ou redimensionados através da chamada MoveWindow, SetWindowPos ou DeferWindowPos.
  • Mensagens de janela não são propagadas principal windows ou de janelas subordinadas, conforme esperado. DefWindowProc com êxito podem não ser propagadas mensagens para a janela principal ou janelas subordinadas da janela de recepção da mensagem.
  • Enviar mensagens de janela para uma janela de chamada EnviarMensagem, SendMessageTimeout ou SendMessageCallback não forem recebidas pela janela especificada.
Além disso, as aplicações que caso contrário, está a funcionar normalmente também poderão detectar os sintomas descritos acima, se WH_CALLWNDPROC ou WH_CALLWNDPROCRET os hooks da janela estiverem definidos em threads na aplicação que pertençam ao windows. Hooks da janela podem ser definidos um tópico específico ou todos os threads de IU, chamando a função SetWindowsHookEx.

Causa


Este comportamento é o resultado do Windows que está a ser não é possível aumentar a pilha do kernel do thread chamada para executar a operação pedida. Devido a pilha do kernel adicionais necessários a x64 os procedimentos de manipulação ambiente Windows, a pilha do kernel pode ser consumida a um ritmo mais rápido num ambiente do Windows quando efectuar recursiva chamadas a funções do Gestor de janela exportado de x86 por USER32. DLL. Apesar dos sintomas descritos neste artigo são mais susceptíveis de ocorrer em x64 plataformas do Windows, é possível para chamadas recursivas para consumir a pilha do kernel do thread no x86 plataformas do Windows.

Resolução


As seguintes soluções podem ser utilizadas para contornar este problema
  1. Redimensione janelas subordinadas quando o processamento de mensagens de janela WM_WINDOWPOSCHANGED em vez disso passar a mensagem para DefWindowProc.
  2. Modo assíncrono redimensione janelas subordinadas quando a janela principal é redimensionada em vez de o redimensionamento de janelas subordinadas ao processar a WM_WINDOWPOSCHANGED ou a mensagem de janela WM_SIZE.
  3. Recriar a aplicação da IU para reduzir a profundidade de janela aninhados.

Mais Informações


Partes do subsistema Win32 são implementados num controlador de dispositivo do modo kernel (WIN32K. SYS). Chamadas a funções exportadas por USER32. DLL para alterar o estado de uma janela, incluindo o respectivo tamanho e posição, efectuará uma chamada no WIN32K. SYS para executar a operação pedida. Funções que modificar o estado de uma janela normalmente resultam em mensagens de janela que está a ser enviadas para a janela que está a ser modificada, onde WIN32K. SYS faz uma chamada de modo de utilizador para chamar o procedimento de janela da janela que está a ser modificado. Por exemplo, WIN32K. SYS enviará uma janela de mensagem da janela de WM_WINDOWPOSCHANGING e uma janela WM_WINDOWPOSCHANGED quando o tamanho e/ou a posição da janela é modificada chamando a função SetWindowPos. DefWindowProc enviará a janela especificada uma mensagem WM_SIZE, quando chamado com uma mensagem WM_WINDOWPOSCHANGED e o tamanho da janela do foi alterado. Aplicações, normalmente, redimensionem janelas subordinadas quando a janela principal recebe uma mensagem de janela WM_WINDOWPOSCHANGED ou WM_SIZE, que conduz a efectuar chamadas recursivas para WIN32K. SYS para hierarquias de janela profundamente aninhadas. Aplicações que caso contrário, está a funcionar normalmente também poderão detectar os sintomas descritos neste artigo quando hooks WH_CALLWNDPROC ou WH_CALLWNDPROCRET estão definidos em threads no processo. Isto deve-se o espaço de pilha do kernel adicionais que seja consumida quando WIN32K. SYS processa a chamar procedimentos de rotina. Chamar EnviarMensagem para enviar uma mensagem de janela para uma janela pertencente o thread de chamada, normalmente, chamará o procedimento de janela de janela de recepção da mensagem sem ter de chamada no WIN32K. SYS. No entanto, EnviarMensagem efectuará uma chamada no WIN32K. SYS se existem rotinas WH_CALLWNDPROC ou WH_CALLWNDPROCRET cria hooks conjunto no thread de chamada, como WIN32K. SYS gere as rotinas de intercepção e as alças de chamar procedimentos de gancho. Tal como indicado acima, DefWindowProc enviará a janela especificada uma mensagem WM_SIZE, quando chamado com uma mensagem WM_WINDOWPOSCHANGED e o tamanho da janela do foi alterado. Uma rotina WH_CALLWNDPROC ou um WH_CALLWNDPROCRET fará com que a chamada EnviarMensagem DefWindowProc torna a transição para o modo de kernel para chamar os procedimentos de rotina. Redimensionar janelas subordinadas quando o processamento de mensagens de janela WM_WINDOWPOSCHANGED em vez de mensagens de janela WM_SIZE reduzirá a utilização da pilha kernel, eliminando a necessidade de EnviarMensagem transitar para o modo de kernel na ordem chamam procedimentos de rotina. Os programadores de aplicações do Windows Forms que encontrar este problema devem referir-se de artigo KB 953934para obter informações adicionais.