Qual é a melhor abordagem para lidar com exceções lançadas em um segmento separado?

votos
4

Eu estou trabalhando em um projeto J2ME que gera threads de trabalho para várias tarefas como o download de conteúdo HTTP. O layout básico da linha é semelhante à maioria dos aplicativos java - não é um dos principais tópicos segmento interface do usuário e de trabalho gerados para fazer coisas nos bastidores. A minha pergunta é qual é a melhor maneira de lidar com exceções que ocorrem nos segmentos de trabalho?

Eu costumo aderir à concepção lógica que a maioria das exceções devem ser infiltrar na medida do possível. Quando eu escrever aplicações single threaded, é comum para mim a se infiltrar as exceções todo o caminho até a camada de interface do usuário e, em seguida, relatá-los em um diálogo de erro para o usuário. Existe uma prática semelhante para aplicativos multithreaded? A coisa mais intuitiva para mim é para capturar exceções no Thread.run () e, em seguida, chamar um invokeLater no segmento interface do usuário para denunciá-lo em uma caixa de diálogo. O problema que vejo aqui é que fora do segmento de trabalho morrendo prematuramente, esta abordagem realmente não notificar o segmento interface do usuário houve um erro. Eu não vejo uma forma clara para lançar uma exceção entre threads por assim dizer.

Obrigado, Andy

Publicado 16/11/2008 em 03:46
fonte usuário
Em outras línguas...                            


2 respostas

votos
7

Você não deve tocar código de UI para os seus trabalhadores!

/**
 * TWO CHOICES:
 * - Monitor your threads and report errors,
 * - setup a callback to do something.
 */
public class ThreadExceptions {

    /** Demo of {@link RunnableCatch} */
    public static void main(String[] argv) throws InterruptedException {
        final Runnable bad = new NaughtyThread();
        // safe1 doesnt have a callback
        final RunnableCatch safe1 = new RunnableCatch(bad);
        // safe2 DOES have a callback
        final RunnableCatch safe2 = new RunnableCatch(bad, new RunnableCallback() {
            public void handleException(Runnable runnable, Exception exception) {
                System.out.println("Callback handled: " + exception.getMessage());
                exception.printStackTrace();
            }

        });
        final Thread t1 = new Thread(safe1, "myThread");
        final Thread t2 = new Thread(safe2, "myThread");
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        if (safe1.getException() != null) {
            System.out.println("thread finished with exceptions");
            safe1.getException().printStackTrace();
        }
        System.out.println("done");
    }


}

/** Throws an exception 50% of the time */
class NaughtyThread implements Runnable {
    public void run() {
        try {
            if (Math.random() > .5) {
                throw new RuntimeException("badness");
            }
        } finally {
            System.out.println("ran");
        }
    }
}

/** Called when an exception occurs */
interface RunnableCallback {
    void handleException(Runnable runnable, Exception exception);
}

/**
 * Catches exceptions thrown by a Runnable,
 * so you can check/view them later and/or
 * deal with them from some callback.
 */
class RunnableCatch implements Runnable {

    /** Proxy we will run */
    private final Runnable _proxy;

    /** Callback, if any */
    private final RunnableCallback _callback;

    /** @guarded-by(this) */
    private Exception _exception;

    public RunnableCatch(final Runnable proxy) {
        this(proxy, null);
    }

    public RunnableCatch(final Runnable proxy, RunnableCallback target) {
        _proxy = proxy;
        _callback = target;
    }

    public void run() {
        try {
            _proxy.run();
        } catch (Exception e) {
            synchronized (this) {
                _exception = e;
            }
            if (_callback != null) {
                _callback.handleException(_proxy, e);
            }
        }
    }

    /** @return any exception that occured, or NULL */
    public synchronized Exception getException() {
        return _exception;
    }
}
Respondeu 16/11/2008 em 05:17
fonte usuário

votos
0

Outra opção diferente do que Stuph tem dado é definir exceções no thread local. Se outra exceção acontece antes que exceção é limpa, em seguida, uma declaração ocorre. Que pelo menos dá a alguém a chance de perceber a exceção e processá-lo.

Respondeu 16/11/2008 em 05:28
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more