O que há de errado com a chamada Invoke, independentemente de InvokeRequired?
-
09-09-2019 - |
Pergunta
Eu vi a configuração comum para o acesso de segmentação cruzada para um controle GUI, tal como discutido aqui: caminho mais curto para gravação um método de acesso thread-safe para um controle Windows Forms
Toda a web bate eu encontrei descrever uma coisa semelhante.
No entanto, por que precisamos de verificar InvokeRequired? Não podemos simplesmente chamar Invoke diretamente?
Presumo que a resposta é não, então a minha verdadeira pergunta é 'porquê'?
Solução
A partir tópicos não-UI não podemos tocar a interface do usuário - coisas muito ruins podem acontecer, uma vez que controles têm afinidade de segmento. Assim, a partir de um não-UI enfiar devemos (a uma minumum) Invoke
chamada ou BeginInvoke
.
Para UI-threads, no entanto - nós não quiser chamar lotes Invoke
de tempo; a questão é que se você são já no segmento interface do usuário, ele ainda tem a sobrecarga desnecessária de enviar uma mensagem a bomba do formulário e processá-lo.
Na realidade, na maioria código de threading você sabe você espera um método específico para ser chamado em um não fio -ui, então, nesses casos, não há nenhum adicional sobrecarga:. apenas chamada Invoke
Outras dicas
InvokeRequired
basicamente diz se você está executando no thread certo ou não. Se você não estiver na linha correta, você precisa organizar a tarefa para o segmento correto de outra forma você não. Daí a necessidade do cheque.
A questão é que os controles GUI tem uma exigência de que apenas código em execução no mesmo segmento que foi usado para instanciar o controle GUI pode acessar o controle GUI. As razões por trás desta exigência está ligada à forma como o Windows é arquitetado. Basta dizer, seria muito difícil mudar isso.
As verificações InvokeRequired a identidade da corrente thread em execução contra a identidade do segmento instantiating. Se eles são o mesmo, o código pode interagir livremente com o controle. Se não, o código deve empacotar os dados através do segmento atual para o segmento instantiating. Isto é um processo lento e dispendioso e é para ser evitada, se possível. Seu código irá funcionar se você sempre invocar e pode ser que você não vai notar o impacto no desempenho, mas este cenário vai ser cada vez mais comum como sistemas multi-core entrar em uso. É melhor não para criar código "nós" que têm de ser desfeita mais tarde.
Se você tentar invocar antes de um identificador de janela é criada (por exemplo, ao chamar forma construtor), você vai ter uma InvalidOperationException
. Então, verificação geral InvokeRequired
é necessária.
MSDN para mais detalhes.
Uma razão que eu posso pensar é performence. Se a maior parte do tempo, o segmento de chamada é o mesmo que o fio criando então você vai ter alguma sobrecarga unnessecry.
O Invoke vai chamar o código através do Delegado e não diretamente que seria caro.
Seu custo eficaz para chamar Invoke apenas quando necessário. Assim, InvokeRequired é usado para descobrir se a chamada está sendo feita a partir de mesmo segmento ou outro segmento?