暂停和恢复SwingWorker.doInBackground() [英] Pause and Resume SwingWorker.doInBackground()

查看:117
本文介绍了暂停和恢复SwingWorker.doInBackground()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个基本的Swing UI,其中有一个标记为Play的按钮。按下按钮时,标签变为暂停。当按下按钮时,它会变为恢复。

I have a basic Swing UI with a single button marked "Play." When the button is pressed the label changes to "Pause". When the button is pressed now it changes to say "Resume."

在播放时我正在实例化并执行SwingWorker。我想要的是能够暂停这个线程(不取消它)并根据上述按钮按下恢复它。但是,我不想在doInBackground()中使用Thread.sleep()。这似乎有点hackish。有没有办法让运行doInBackground的线程阻塞?

On "Play" I am instantiating and executing a SwingWorker. What I would like is to be able to pause this thread (NOT cancel it) and resume it according to the button presses described above. However, I'd prefer not to resort to Thread.sleep() in doInBackground(). That seems a bit hackish. Is there any way for the thread running doInBackground to block?

推荐答案


暂停和恢复SwingWorker.doInBackground ()

Pause and Resume SwingWorker.doInBackground()

首先,您必须确保正在执行的后台任务可以暂停,否则问题没有意义。因此,假设任务可以暂停,那么您可以延长 SwingWorker 类并使用简单的标志变量创建您自己的可暂停工作程序来控制后台线程状态:暂停不暂停

First of all you have to be sure the background task being performed can be paused, otherwise the question doesn't make sense. So let's say the task can be paused, then you might extend SwingWorker class and make your own pausable worker using a simple flag variable to control the background thread status: paused or not paused.

public abstract class PausableSwingWorker<K, V> extends SwingWorker<K, V> {

    private volatile boolean isPaused;

    public final void pause() {
        if (!isPaused() && !isDone()) {
            isPaused = true;
            firePropertyChange("paused", false, true);
        }
    }

    public final void resume() {
        if (isPaused() && !isDone()) {
            isPaused = false;
            firePropertyChange("paused", true, false);
        }
    }

    public final boolean isPaused() {
        return isPaused;
    }
}

子类可能会检查 isPaused( )状态,以便有效地继续执行任务。例如:

Subclasses might check isPaused() status in order to efectively proceed with the task or not. For example:

PausableSwingWorker<Void, String> worker = new PausableSwingWorker<Void, String>() {
    @Override
    protected Void doInBackground() throws Exception {
        while (!isCancelled()) {
            if (!isPaused()) {
                // proceed with background task
            } else {
                Thread.sleep(200); // Optional sleep to avoid check status continuously
            }
        }
        return null;
    }
};

您还可以添加 PropertyChangeListener 到工作人员并监听暂停属性更改:

You can also add a PropertyChangeListener to the worker and listen for paused property changes:

worker.addPropertyChangeListener(new PropertyChangeListener() {
    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        if ("paused".equals(evt.getPropertyName())) {
           System.out.println("Old status: " + evt.getOldValue());
           System.out.println("New status: " + evt.getNewValue());
        }
    }
});






示例(更新以使用PropertyChangeListener)



这是一个完整的例子。请注意,如果工作人员被停止,则不能再暂停或恢复工作。


Example (updated to make use of PropertyChangeListener)

Here is a complete example to play with. Please note that if worker is stopped then it cannot be paused nor resumed anymore.

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

public class Demo {

    private void createAndShowGUI() {

        final JTextArea textArea = new JTextArea(20, 50);

        final PausableSwingWorker<Void, String> worker = new PausableSwingWorker<Void, String>() {
            @Override
            protected Void doInBackground() throws Exception {
                while (!isCancelled()) {
                    if (!isPaused()) {
                        publish("Writing...");
                    } else {
                        Thread.sleep(200);
                    }
                }
                return null;
            }

            @Override
            protected void process(List<String> chunks) {
                String text = String.format("%s%n", chunks.get(chunks.size() - 1));
                textArea.append(text);
            }
        };

        worker.addPropertyChangeListener(new PropertyChangeListener() {
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                if ("paused".equals(evt.getPropertyName())) {
                    String text = (Boolean)evt.getNewValue() ? "Paused..." : "Resumed...";
                    textArea.append(String.format("%s%n", text));
                }
            }
        });

        Action pause = new AbstractAction("Pause") {
            @Override
            public void actionPerformed(ActionEvent e) {
                worker.pause();
            }
        };

        Action resume = new AbstractAction("Resume") {
            @Override
            public void actionPerformed(ActionEvent e) {
                worker.resume();
            }
        };

        Action stop = new AbstractAction("Stop") {
            @Override
            public void actionPerformed(ActionEvent e) {
                worker.cancel(true);
            }
        };

        JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
        buttonsPanel.add(new JButton(pause));
        buttonsPanel.add(new JButton(resume));
        buttonsPanel.add(new JButton(stop));

        JPanel content = new JPanel(new BorderLayout(8, 8));
        content.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
        content.add(new JScrollPane(textArea), BorderLayout.CENTER);
        content.add(buttonsPanel, BorderLayout.SOUTH);

        JFrame frame = new JFrame("Demo");
        frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                if (!worker.isDone()) {
                    worker.cancel(true);
                }
                e.getWindow().dispose();
            }
        });

        frame.add(content);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);

        worker.execute();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Demo().createAndShowGUI();
            }
        });
    }

    abstract class PausableSwingWorker<K, V> extends SwingWorker<K, V> {

        private volatile boolean isPaused;

        public final void pause() {
            if (!isPaused() && !isDone()) {
                isPaused = true;
                firePropertyChange("paused", false, true);
            }
        }

        public final void resume() {
            if (isPaused() && !isDone()) {
                isPaused = false;
                firePropertyChange("paused", true, false);
            }
        }

        public final boolean isPaused() {
            return isPaused;
        }
    }
}

这篇关于暂停和恢复SwingWorker.doInBackground()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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