Pergunta

Estou usando o Scintilla Edit Control no Windows (Win32, C/C ++). O controle é criado no WNDPROC. Eu tenho um segundo tópico, criado com boost.thread, que atua como verificador ortográfico e marcas com palavras vermelhas de gravação incorretamente. Portanto, tenho dois threads que alteram o conteúdo do controle do Scintilla.

No começo, o programa estava travando ao editar o texto. Então eu pesquisei Scintilla para segurança de threads. Encontrei pouca informação, mas consigo obter esta cotação na documentação:

A chamada direta causará problemas se executada de um encadeamento diferente para o encadeamento nativo da janela Scintilla, nesse caso, o sendMessage (hsciwnd, sci_*, wparam, lparam) deve ser usado para sincronizar com o encadeamento da janela.

Obviamente, estou usando chamadas diretas, de acordo com todas as chamadas no thread de verificação ortográfica para SendMessage e agora o programa não trava mais. Finalmente, e essa é a pergunta, resolvi o problema, ou vou encontrar outras peculiaridades com Scintilla e Multithreads?

Foi útil?

Solução

Geralmente você deve acessar o Windows (HWNDs) No Windows, apenas a partir do encadeamento em que foram criados. Qualquer mensagem enviada para a janela será executada no thread que o criou, é por isso que as falhas pararam de acontecer quando você substituiu todas as chamadas diretas para as funções do Scintilla enviando mensagens. Se você usar SendMessage() No seu tópico de verificação ortográfico, isso fará com que o seguinte aconteça:

  • O tópico de verificação ortográfico vai bloquear
  • Uma mudança de contexto para o thread da GUI será executada
  • O loop da mensagem processará a mensagem (mas não necessariamente imediatamente, as mensagens na fila serão tratadas na ordem em que foram adicionadas; portanto, a mensagem será tratada somente depois que todas as mensagens adicionadas anteriormente foram tratadas)
  • Uma mudança de contexto para o segmento de verificação ortográfica será executada
  • a SendMessage() Chamada retorna o resultado

Então você realmente resolveu o problema, mas a um preço muito alto. Cada palavra errônea causará dois interruptores de contexto de threads, e a verificação de ortografia será bloqueada para cada palavra incorreta. Na verdade, isso pode demorar muito tempo, se outras mensagens que demorarem muito para lidar ainda estivessem na fila.

Você deve alterar o design do seu programa. Idealmente, ambos os threads poderão funcionar de forma independente, e isso pode ser alcançado adicionando uma estrutura de dados segura por encadeamento que o encadeamento de verificação ortográfico adiciona informações sobre as palavras incorretas e que o thread principal recupera as informações. O Boost tem muitas aulas para ajudá -lo. Ao fazer isso, você pode continuar usando as chamadas diretas, pois elas serão realizadas no contexto do encadeamento principal. O desempenho deve melhorar, pois várias palavras podem ser sublinhadas de uma só vez, causando apenas uma única repintura do controle. Se você usar PostMessage() ao invés de SendMessage() O encadeamento de verificação ortográfico poderá continuar seu trabalho independentemente do encadeamento principal pronto para lidar com a mensagem.

Se você se lembra de nunca chamar nenhum código de scintilla dos threads secundários, não encontrará outras peculiaridades. E isso não é nada específico para o controle do Scintilla, chamando as funções da API do Windows que não usam mensagens do Windows internamente seriam problemáticas para qualquer outro controle também.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top