Pergunta

Em meu aplicativo SWT Java, geralmente desejo retornar informações de dentro de uma chamada Display.syncExec().A melhor maneira que encontrei até agora de fazer isso é:

final ArrayList<Integer> result = new ArrayList<Integer>();
GUI.display().syncExec(new Runnable(){ public void run() {
   MessageBox mb = /* ... */;
    /* set up messagebox */
   result.add(mb.open());
}});
if (SWT.OK == result.get(0)) { /* ... */ }

Acho que isso é permitido porque ArrayList é seguro para threads, mas existe um contêiner melhor que eu deveria usar ou uma maneira mais fácil?

Foi útil?

Solução

ArrayList não é thread-safe.Você pode obter um thread-safe List com Collections.synchronizedList.Entretanto, é muito mais simples usar um AtomicInteger no seu caso ou AtomicReference num caso mais geral.

final AtomicInteger resultAtomicInteger = new AtomicInteger();
Display.getCurrent().syncExec(new Runnable() { 
    public void run() {
        MessageBox mb = /* ... */;
            /* set up messagebox */
        resultAtomicInteger.set(mb.open());
}});
if (SWT.OK == resultAtomicInteger.get()) { /* ... */ }

Outras dicas

Acabei de resolver esse problema e minha primeira tentativa foi semelhante - matriz ou lista de itens do tipo desejado.Mas depois de um tempo eu inventei algo assim:

abstract class MyRunnable<T> implements Runnable{
    T result;
}
MyRunnable<Integer> runBlock = new MyRunnable<Integer>(){
   MessageBox mb = /* ... */;
    /* set up messagebox */
   result = mb.open();
}
GUI.display().syncExec(runBlock);
runBlock.result; //holds a result Integer

É muito mais organizado e remove variáveis ​​redundantes.

POR FALAR NISSO.Minha primeira tentativa foi usar o UIThreadRunnable, mas eu não queria a dependência do SWTBot, então abandonei essa solução.Depois que fiz minha própria solução, descobri que eles usam um trabalho semelhante lá.

ArrayList é não discussão segura.Do relevante Javadoc:

Observe que esta implementação não é sincronizada.Se vários threads acessarem uma instância do Arraylist simultaneamente e pelo menos um dos threads modifica a lista estruturalmente, ela deve ser sincronizada externamente.

Se você precisar de uma implementação thread-safe de List, há (pelo menos) duas fornecidas no JDK:CopyOnWriteArrayList e vetor.

Você poderia usar um array Integer[1] para torná-lo mais conciso, mas não acho que ele possa atualizar diretamente uma variável não final de dentro de uma classe interna anônima.

final Integer[] result = new Integer[1];

Achei que você deveria declarar os resultados como finais (mas essa mudança não afetaria seu código).Como o Thread atual é bloqueado até que o Thread interno seja concluído, não acho que você precise se preocupar com a sincronização (mas pode ser necessário violar a variável para ver o resultado).

Se isso acontecer com frequência, é melhor usar o modelo de assinatura/notificação entre seu processo e visualização.Sua visualização se inscreve no evento que deve acionar aquela caixa de mensagem e é notificada quando as condições são atendidas.

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