Swing Frage zu invokeAndWait() Exceptions

hdi

Top Contributor
hey leute,

Diese ganze EDT Geschichte schafft es leider selbst nach jahren noch immer mich manchmal zu verwirren 😀 wenn man ein invokeAndWait hat dann können da ja 2 Exceptions fliegen:

Java:
		try {
			SwingUtilities.invokeAndWait(new Runnable() {
				@Override
				public void run() {
				
				}
			});
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}


Ich hab so ein invokeAndWait grad im Code und jetzt würde ich gern per JOptionPane.showXXX() ne Meldung anzeigen wollen wenn eine Exception fliegt. Und da ja auch diese Klasse/Methode nicht thread-safe ist und und von Swing kommt sollte man den Code ja wiederum per invokeLater auf den EDT legen. Frage: Hab ich dann ein Deadlock? Ich weiß nämlich nich genau was ich mir unter den Exceptions vorstellen soll, also was "geht ab" mit dem EDT wenn so ne Exception fliegt?

Testen kann ich das leider nicht, denn ich kann die Effekte ja nich ausm Hut ziehen die da beim EDT passieren wenn sowas tatsächlich auftritt..

Generell noch ne Frage zu JOptionPane: Muss man das eig auf den EDT legen? Immerhin kann es doch bei diesen Dialogen nich wirklich dazu kommen das 2 Threads darauf zugreifen. Aber wer weiß schon was da sonst alles unter der Haube passiert wenn man die Methoden aufruft...

Danke für Antwort!
 
hey leute,
Testen kann ich das leider nicht, denn ich kann die Effekte ja nich ausm Hut ziehen die da beim EDT passieren wenn sowas tatsächlich auftritt..

Du meinst etwas, was darüber hinausgeht, dass man Thread.interrupt() aufruft unt die Exception per Hand wirft? (Die InvocationTargetException wickelt ja nur andere Exceptions ein...)
 
Du meinst etwas, was darüber hinausgeht, dass man Thread.interrupt() aufruft unt die Exception per Hand wirft?

Ja das ist halt die Frage, ob da nich noch mehr passiert. Ich bin mir halt nich wirklich sicher, ob das so iO ist mit nem JOptionPane per invokeLater im catch block. Wer weiß in welchem Zustand sich der EDT gerade befindet, wenn du verstehst was ich meine. Ist für mich grad nich wirklich transparent..
 
Danke, aber ich finde den Artikel etwas seltsam bzw verstehe ihn nicht. Er hat da ne ThreadGroup gemacht bei der geworfene Exceptions von Threads immer behandelt werden, ist ja ganz nett, aber was hat das jetzt mit dem EDT zu tun? Er führt seinen Code doch gar nich auf dem EDT aus? ???:L D.h. er ignoriert doch total die Existenz des EDT und die Tatsache dass GUI Code darauf ausgeführt werden sollte, oder peil ich das nur nicht?
 
Also die ganzen Dinge, die die Exceptions auslösen, werden ja schon auf dem EDT gemacht. Und wenn dort eine Exception fliegt, dann stirbt der EDT, bis ein neuer Event verarbeitet werden muss.
Oder meinst du, dass das showMessageDialog nicht auf dem EDT gemacht wird? Dort wird ein modaler Dialog angezeigt, für den quasi ein neuer EDT gestartet wird, d.h. das kann von jedem Thread aus gemacht werden.
 
Also die ganzen Dinge, die die Exceptions auslösen, werden ja schon auf dem EDT gemacht.
Ja eben, aber was bringt ihm dann seine ThreadGroup? Ich verstehe nicht wieso die uncaughtException() Methode seiner ThreadGroup ausgelöst werden sollte wenn es doch der EDT ist, der die Exception wirft, und nicht der Thread, den er in diese ThreadGroup gelegt hat. Verstehst du was ich meine. Wo ist die Verbindung, wieso funktioniert das so wie ers im Artikel sagt? die acitonPerformed() wird vom EDT ausgeführt, nicht von dem Thread wo er den Code mit der GUI usw drin hat. Wenn da ne Exception fliegt, wieso kommt die plötzlich in irgendeiner Methode von irgendeiner ThreadGroup an?
 
Die ThreadGroup eines Threads ist standardmäßig die gleiche, wie von dem Thread, die den Thread erzeugt - in diesem Fall würden also alle EDT Threads zu der ThreadGroup gehören, die dort erstellt wird.

Wobei eigentlich das Erstellen der Gui-Components schon auf dem EDT stattfinden sollte. D.h. eigentlich müßte man DAS nochmal in die SwingUtilities einwickeln...
Java:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class BetterGui
{
    public static void main(String[] args)
    {
        ThreadGroup exceptionThreadGroup = new ExceptionGroup();
        new Thread(exceptionThreadGroup, "Init thread")
        {
            public void run()
            {
                SwingUtilities.invokeLater(new Runnable()
                {
                    public void run()
                    {
                        Gui gui = new Gui();
                        gui.pack();
                        gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                        gui.setVisible(true);
                    }
                });
            }
        }.start();
    }
}

class Gui extends JFrame
{
    public Gui()
    {
        super("GUI Example");
        final JTextArea text = new JTextArea(14, 30);
        getContentPane().add(new JScrollPane(text));
        getContentPane().add(new JButton(new AbstractAction("Calculate")
        {
            private int countdown = 3;

            public void actionPerformed(ActionEvent e)
            {
                text.append("Event Queue Thread: " +
                    System.identityHashCode(Thread.currentThread()) +
                    " Group: " + Thread.currentThread().getThreadGroup());
                text.append("\n");
                if (--countdown <= 0)
                {
                    throw new IllegalArgumentException();
                }
            }
        }), BorderLayout.NORTH);
    }
}

class ExceptionGroup extends ThreadGroup
{
    public ExceptionGroup()
    {
        super("ExceptionGroup");
    }

    public void uncaughtException(Thread t, Throwable e)
    {
        JOptionPane.showMessageDialog(findActiveFrame(), e.toString(),
            "Exception Occurred", JOptionPane.ERROR_MESSAGE);
        e.printStackTrace();
    }

    /**
     * I hate ownerless dialogs. With this method, we can find the currently
     * visible frame and attach the dialog to that, instead of always attaching
     * it to null.
     */
    private Frame findActiveFrame()
    {
        Frame[] frames = JFrame.getFrames();
        for (int i = 0; i < frames.length; i++)
        {
            Frame frame = frames[i];
            if (frame.isVisible())
            {
                return frame;
            }
        }
        return null;
    }
}
 

Zurück
Oben