achilles
achilles

Reputation: 119

Repeat the execution of a SwingWorker in Java

I was reading through multiple posts and I wasn't able to find a clear answer to my question.

I have an application (Main Frame) that has a start and a stop button and just a jTextArea. When a user presses the "start" button, a SwingWorker class is instantiated and runs (execute()) a task. That task is to connect to a database and do some checks. For every check, it updates the jTextArea correctly and everything is fine. When the stop button is pressed, i set the isCancelled() to true and thus the background process stops (I have the appropriate checks inside the SwingWorker to stop execution etc).

What I want to do is when the user presses "Start", the SwingWorker starts execution, sleeps for a few minutes and then re-runs the same task. When the "Stop" button is pressed, everything stops.

How can I achieve that? I understand that a SwingWorker background process is supposed to be run once. What would other ways of doing this be? Note that the reason I picked a SwingWorker was because I wanted to update the jTextArea while the background process runs.

Thank you in advance.

Upvotes: 1

Views: 1873

Answers (2)

Nico Pretorius
Nico Pretorius

Reputation: 16

I normally use a loop inside the swingworker, works fine.

Global Variables

private boolean monitor = true;

Swingworker Class

private class MonitorQueue extends SwingWorker<Void, Void> {

    @Override
    protected Void doInBackground() throws Exception {
        while (monitor) {
            System.out.println("monitor");
            Thread.sleep(Constants.SECOND * 5);
        }
        return null;
    }
}

Added advantage that I have is instead of stopping or pausing the SwingWorker itself, I just set monitor = false. This will let the SwingWorker finish all tasks before stopping.

Upvotes: 0

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285401

You can run a SwingWorker once and only once, without exception. Possible solutions include:

  • Create a new SwingWorker object each time one is needed, run it, and stop and discard it when done.
  • Run a single SwingWorker throughout the run of your program, do not cancel it when stop is pressed, but rather pause it (how will depend on the non-Swing portion of the code that we don't know about), and awaken it when play is pressed. A state design pattern could work well for this.

Regarding your statement,

What I want to do is when the user presses "Start", the SwingWorker starts execution, sleeps for a few minutes and then re-runs the same task. When the "Stop" button is pressed, everything stops.

Consider using a ScheduledExecutorService for this inside of the SwingWorker. The ScheduledExecutorService creates a ScheduledFuture<V> which can be canceled if the need arises.


Edit
Your comments and my responses:

Wouldn't a ScheduledExecutorService cause the background process to run multiple times?

No. The background process would be run once. The Futures created by the ScheduledExecutorService would also be created and then run at their scheduled times.

What would happen, for example, when the delay is less than the time it took the previous iteration to run?

Multiple Futures would be created and would start running simultaneously.

Should I just go with a while loop inside the doInBackground() with a Thread.Sleep()?

It's so very hard to tell based on what we know about your current project. This could potentially work, yes, but for more complex needs, then no, you would want to use the ScheduledExecutorService.

Upvotes: 5

Related Questions