Uso do JavaFX Platform.runLater e access à interface do usuário de um segmento diferente

Eu tenho algumas perguntas sobre Platform.runLater . Eu tenho uma class de aplicativo JavaFX. Nesta class eu corro um thread (o thread lê dados de um socket de rede).

Agora, quando eu crio um novo Stage dentro do thread, o sistema lança uma execption (thread do dispatcher do evento JavaFX e meu thread netork-read não são os mesmos) – Eu entendo esse comportamento.

Mas o outro lado é, eu acrescento o texto do leitor de rede a um TextArea existente ou adiciono / removo alguns itens em um ListView – isso não gera uma exceção – por quê? Eu pensei que o JavaFX é singlethreaded (A parte da biblioteca ui). É a mesma coisa que no Swing: Às vezes funciona e às vezes você tem apenas lixo (porque EDT)?

Minhas perguntas:

  • Quando o encadeamento de dispatcher de events do JavaFX lança uma exceção e quando não?
  • São os documentos bons sobre isso?
  • Existe uma maneira mais fácil (mais curta e mais limpa) de usar Platform.runLater com um método run() ? Em combinação com um try catch (ou várias capturas), parece muito estranho

Eu sei que o uso de Platform.runLater em um segmento não é legal (solução de design)

“isso não gera uma exceção – por quê?” porque nem todos esses casos são encontrados … Possivelmente, devido a considerações de desempenho, possivelmente, é apenas uma funcionalidade perdida.

Todas as interações com objects JavaFX (incluindo criação) devem ser feitas no encadeamento JFX, se você desejar acessar esses objects JFX de outro encadeamento – use os methods runLater ou runAndWait. Se não der uma exceção agora, possivelmente começará a lançar exceções no futuro. Qualquer interação com o object JFX pode causar ações e events subsequentes, que serão encontrados por algum verificador de threads – você não pode ter certeza.

Eu não acho, há qualquer boa documentação sobre isso – apenas uma regra simples – use runLater ou runAndWait.

Maneira mais curta e mais limpa – será fornecida no JDK 8 usando o Lambda.

A resposta de Alexander capta os pontos mais importantes em relação às suas perguntas.

Esta resposta fornece algumas informações suplementares.

Quando o encadeamento de dispatcher de events do JavaFX lança uma exceção e quando não?

O sistema JavaFX nem sempre verifica se os accesss aos objects que afetam o gráfico de cena ativo estão adequadamente restritos ao encadeamento do JavaFX. Por fim, garantir essa segurança de thread é responsabilidade do programador de aplicativos JavaFX – não do sistema JavaFX. Você deve ter muito cuidado ao executar a programação multi-thread no JavaFX, caso contrário, o comportamento do aplicativo pode falhar ou ficar imprevisível.

São os documentos bons sobre isso?

Experimente o tutorial do JavaFX: concurrency no JavaFX .

Existe uma maneira mais fácil (mais curta e mais limpa) de usar Platform.runLater com um método run ()?

Não. Platform.runLater é tão simples quanto possível.


Como um aparte. . .

Tarefa e Serviço

Considere o uso das subclasss Tarefa ou Serviço do Trabalhador . Esses são os wrappers do JavaFX para o FutureTask (que por sua vez é um Runnable ). Os trabalhadores fornecem um método de chamada para executar a lógica em um thread de segundo plano. Eles mantêm o status de execução (com notificação de retorno de chamada segura de thread ao thread do JavaFX para alterações de estado) e retornam resultados da chamada por meio de propriedades de valor , mensagem e exceção .

Aproveite os padrões de design nos exemplos de javadoc Task and Service para simplificar a criação de aplicativos thread-safe com resources como:

  • Recuperação assíncrona de dados para atualização da interface do usuário.
  • Atualizações periódicas de mensagens para o progresso da tarefa.
  • Construindo charts de nós que ainda não estão anexados a uma cena exibida.
  • Monitorando o progresso através de barras de progresso, etc.

Um Worker é complementar ao Platform.runLater . Use Platform.runLater quando estiver executando o encadeamento do aplicativo JavaFX e desejar executar alguma lógica no encadeamento do aplicativo JavaFX. Use um Worker quando estiver executando no JavaFX Application Thread e quiser gerar alguma lógica ou (especialmente) E / S em um novo thread para que você não bloqueie o JavaFX Application Thread. Você nunca desejaria fazer E / S de rede dentro de um método de run Platform.runLater , mas geralmente desejaria fazê-lo em um método de call Worker .

Além disso, o uso de Task e Service não é incompatível com o uso de Platform.runLater . Por exemplo, se você tiver uma Task execução muito longa da qual deseja retornar resultados parciais à IU periodicamente ou como um buffer é preenchido, a execução de Platform.runLater no método de call da tarefa é a maneira de fazer isso.

Os trabalhadores são úteis quando você não possui um serviço encadeado existente fornecido por uma biblioteca, mas, ao invés disso, cria seus próprios encadeamentos para execução em segundo plano. Se você tiver um serviço encadeado existente, será necessário usar Platform.runLater para executar a lógica no encadeamento do aplicativo JavaFX.

Observe que você ainda precisa saber o que está fazendo, mesmo se usar um Worker . Você ainda deve tomar cuidado para não violar regras de simultaneidade JavaFX padrão, como nunca atualizar Nós no gráfico de cena ativo (incluindo a não atualização de valores que os Nós no gráfico de cena ativo estão vinculados), como a lista observável de itens um ListView ).

    Intereting Posts