Java SwingWorker不会在任务完成时终止 [英] Java SwingWorker not terminating on task completion

查看:51
本文介绍了Java SwingWorker不会在任务完成时终止的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好,所以我一直在与SwingWorker一起玩,并获得了一些简化的代码来更新gui,但是我在弄清楚如何使线程在完成时正确终止方面遇到了麻烦.当前,它仅通过stop选项终止.我如何设置它以在完成其进程时也正确终止该线程?当前,return null;之后进入包装行并挂起.

Ok, so I've been playing around with SwingWorker a bit and got some simplified code for updating a gui going, but I'm having trouble figuring out how to get the thread to properly terminate when it completes. Currently, it is only terminating via the stop option. How would I set it up to also terminate the thread properly when it finishes its process? Currently, after the return null; it goes to the package line and hangs.

我的代码如下:

    package concurrency;

import java.util.List;
import java.util.Random;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.Insets;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

public class PBTest extends JFrame implements ActionListener {
    private final GridBagConstraints constraints;
    private final JProgressBar pb, pbF;
    private final JButton theButton;
    private PBTask pbTask;

    private JProgressBar makePB() {
        JProgressBar p = new JProgressBar(0,100);
        p.setValue(0);
        p.setStringPainted(true);
        getContentPane().add(p, constraints);
        return p;       
    }

    public PBTest() {
        super("PBTest");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Make text boxes
        getContentPane().setLayout(new GridBagLayout());
        constraints = new GridBagConstraints();
        constraints.insets = new Insets(3, 10, 3, 10);

        pb = makePB();
        pbF = makePB();

        //Make buttons
        theButton = new JButton("Start");
        theButton.setActionCommand("Start");
        theButton.addActionListener(this);
        getContentPane().add(theButton, constraints);

        //Display the window.
        pack();
        setVisible(true);
    }

    private static class UpdatePB {
        private final int pb1, pb2;
        UpdatePB(int pb1s, int pb2s) {
            this.pb1 = pb1s;
            this.pb2 = pb2s;
        }
    }

    private class PBTask extends SwingWorker<Void, UpdatePB> {
        @Override
        protected Void doInBackground() {
            int prog1 = 0;
            int prog2 = 0;
            Random random = new Random();

            while (prog2 < 100) {
                if(prog1 >= 100) {
                    prog1 = 0;
                }
                //Sleep for up to one second.
                try {
                    Thread.sleep(random.nextInt(1000));
                } catch (InterruptedException ignore) {}
                //Make random progress.
                prog1 += random.nextInt(10);
                prog2 += random.nextInt(5);
                publish(new UpdatePB(prog1, prog2));
            }
            return null;
        }

        @Override
        protected void process(List<UpdatePB> pairs) {
            UpdatePB pair = pairs.get(pairs.size() - 1);
                pb.setValue(pair.pb1);
                pbF.setValue(pair.pb2);
        }
    }

    public void actionPerformed(ActionEvent e) {
        if ("Start" == e.getActionCommand() && pbTask == null) {
            theButton.setText("Stop");
            theButton.setActionCommand("Stop");
            (pbTask = new PBTask()).execute();
        } else if ("Stop" == e.getActionCommand()) {
            theButton.setText("Start");
            theButton.setActionCommand("Start");
            pbTask.cancel(true);
            pbTask = null;
        } else {
            alertMsg("Thread still running.");
        }

    }

    static void alertMsg(String theAlert) {
        JOptionPane.showMessageDialog(null, theAlert);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new PBTest();
            }
        });
    }
}

注意:这基本上是Java教程的"flipper"示例的替代方案……目前,我不是程序员,而是代码黑客(/sad face/,大声笑),所以我下一步该怎么走.

Note: this is basically an alteration of the Java tutorials' "flipper" example... I'm not so much a programmer as a code hacker (/sad face/, lol), at the moment, so I'm kind of at a loss as to where to go next.

无论如何,代码将按预期工作,直到完成为止.我尝试添加done()方法,但是它从未尝试运行它,它始终只是转到程序包行(单步执行调试器时)并挂起.我是否应该返回null或其他值以外的值?

Anyway, the code works as intended until it finishes. I tried adding the done() method, but it never attempts to run it, it always just goes to the package line (when stepping through the debugger) and hangs. Am I supposed to return a value other than null or something?

在此先感谢您的帮助!

推荐答案

我不确定您要达到的目标. 您的示例工作正常.辅助线程一直运行到最后. 万一您想等到它完成某件事时,就必须在代码中的某个地方调用方法pbTask.get().否则,它将安静地完成而不会影响您的任何UI组件.

I'm not sure what you're trying to achieve. Your example is working fine. Worker thread runs till the end. In case you want to wait till it ends to do something, you have to call method pbTask.get() somewhere in your code. Otherwise, it will just quietly completes without affecting any of your UI components.

请考虑对您的方法进行以下更改,以查看其现在的行为.请注意,UI冻结是因为您让UI等待线程完成,但是只有在WorkerThread完成时,输出"DONE"才会出现在日志中.

Consider the following change to your method to see how it behaves now. Note, that UI freezes because you make UI wait for the thread to complete, but output "DONE" appears in your log only when the WorkerThread completes.

public void actionPerformed(ActionEvent e) {
    if ("Start" == e.getActionCommand() && pbTask == null) {
        theButton.setText("Stop");
        theButton.setActionCommand("Stop");
        (pbTask = new PBTask()).execute();
    } else if ("Stop" == e.getActionCommand()) {
        theButton.setText("Start");
        theButton.setActionCommand("Start");
        pbTask.cancel(true);
        pbTask = null;
    } else {
        alertMsg("Thread still running.");
    }
    try {
        pbTask.get();
    } catch (InterruptedException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    } catch (ExecutionException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
    System.out.println("DONE");
}

此更改只是为了说明差异.为了编写实际的代码,我们需要更多地了解您要实现的目标.

This change is just to illustrate the difference. In order to write actual code we need to know more about what you're trying to achieve.

如果我的超感官技能还不错,那么您可能希望将按钮翻转回开始".为此,您需要在Worker中重写done()方法:

If my extrasensory skills are ok, then you probably want to flip button back to "Start". In order to do this, you need to override done() method in the Worker:

private class PBTask extends SwingWorker<Void, UpdatePB> {
    @Override
    protected Void doInBackground() {
        int prog1 = 0;
        int prog2 = 0;
        Random random = new Random();

        while (prog2 < 100) {
            if(prog1 >= 100) {
                prog1 = 0;
            }
            //Sleep for up to one second.
            try {
                Thread.sleep(random.nextInt(100));
            } catch (InterruptedException ignore) {}
            //Make random progress.
            prog1 += random.nextInt(10);
            prog2 += random.nextInt(5);
            publish(new UpdatePB(prog1, prog2));
        }
        return null;
    }

    @Override
    protected void process(List<UpdatePB> pairs) {
        UpdatePB pair = pairs.get(pairs.size() - 1);
            pb.setValue(pair.pb1);
            pbF.setValue(pair.pb2);
    }

    @Override
    protected void done() {
        super.done();
        theButton.setText("Start");
        theButton.setActionCommand("Start");
    }
}

这篇关于Java SwingWorker不会在任务完成时终止的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆