简体   繁体   English

有什么区别吗? SwingWorker#publish 与 SwingUtilities#invokeLater

[英]Is there any difference? SwingWorker#publish vs SwingUtilities#invokeLater

Let's say we have a long/heavy task that must run in background, and publish its progress or whatever to the GUI.假设我们有一个长期/繁重的任务,必须在后台运行,并将其进度或其他内容发布到 GUI。 I know that this publishing must happen on the event dispatch thread.我知道这种发布必须发生在事件调度线程上。 That's why we use a SwingWorker for the task.这就是我们使用SwingWorker来完成任务的原因。

So, what we do, is something like this:所以,我们所做的,是这样的:

public class WorkerTest {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("test");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setLayout(new FlowLayout());

            JLabel label = new JLabel();
            frame.add(label);
            startWorker(label);

            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
        });
    }

    private static void startWorker(JLabel label) {
        new SwingWorker<Integer, Integer>() {

            @Override
            protected Integer doInBackground() throws Exception {
                for (int i = 0; i < 500; i++) {
                    publish(i);
                    Thread.sleep(500); //Simulate long task
                }
                return null;
            }

            @Override
            protected void process(List<Integer> chunks) {
                Integer integer = chunks.get(0);
                label.setText(String.valueOf(integer));
            }
        }.execute();
    }
}

My question is, how the above differs from this:我的问题是,以上与此有何不同:

private static void startWorker(JLabel label) {
    new SwingWorker<Integer, Integer>() {

        @Override
        protected Integer doInBackground() throws Exception {
            for (int i = 0; i < 500; i++) {
                int i2 = i;
                SwingUtilities.invokeLater(() -> {
                    label.setText(String.valueOf(i2));
                });
                Thread.sleep(500); //Simulate long task
            }
            return null;
        }

    }.execute();
}

In both cases, the label.setText() which is an update to the GUI, runs to the Event dispatch thread.在这两种情况下,作为 GUI 更新的label.setText()运行到事件调度线程。 How are they different?它们有何不同?

Of course, the question stands also why should I implement a done() method to the worker vs calling SwingUtilities.invokeLater at the end of the doInBackground method?当然,问题还在于为什么我应该对工作人员实施done()方法而不是在doInBackground方法的末尾调用SwingUtilities.invokeLater Besides handling the exception possibly thrown in doInBackground method.除了处理doInBackground方法中可能抛出的异常。

Look at the javadoc for method publish() in class SwingWorker .查看类SwingWorker方法publish()javadoc

Because the process method is invoked asynchronously on the Event Dispatch Thread multiple invocations to the publish method might occur before the process method is executed.因为 process 方法是在 Event Dispatch Thread 上异步调用的,所以在 process 方法执行之前可能会发生对 publish 方法的多次调用。 For performance purposes all these invocations are coalesced into one invocation with concatenated arguments.出于性能目的,所有这些调用都合并为一个带有连接参数的调用。

Calling SwingUtilities.invokeLater() directly from method doInBackground() does not perform the coalescing – according to the code in your question.根据您问题中的代码,直接从方法doInBackground()调用SwingUtilities.invokeLater()不会执行合并。 Perhaps you can think of a reason why the coalescing is necessary?也许你能想到一个为什么需要合并的原因? Also refer to Tasks that Have Interim Results另请参阅具有中期结果的任务

Regarding method done() in class SwingWorker , that you also asked about, again I refer you to the javadoc关于类SwingWorker方法done() ,您也询问过,我再次将您推荐给javadoc

Executed on the Event Dispatch Thread after the doInBackground method is finished. doInBackground 方法完成后在事件调度线程上执行。 The default implementation does nothing.默认实现什么都不做。 Subclasses may override this method to perform completion actions on the Event Dispatch Thread.子类可以重写此方法以在事件调度线程上执行完成操作。 Note that you can query status inside the implementation of this method to determine the result of this task or whether this task has been cancelled.请注意,您可以在此方法的实现内部查询状态,以确定此任务的结果或此任务是否已被取消。

So you don't have to override method done() .所以你不必覆盖方法done() Personally, I usually add a property listener to my SwingWorker object for handling tasks that I need to perform once the [ SwingWorker ] task has completed.就我个人而言,我通常向我的SwingWorker对象添加一个属性侦听器,用于处理在 [ SwingWorker ] 任务完成后需要执行的任务。 But of-course, YMMV.但当然,YMMV。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM