Run a background task when certain events occur in a screen a user is on

Hello,

I’m trying to make use of a background task in my screen controller by executing it whenever a user completes certain tasks on the screen.

If I try and do this more than once, I get this exception thrown: IllegalStateException: Task is already started. I also noticed the background task is staying in the list of threads stuck on WAITING in the Performance Statistics section of the app. I’m assuming this is why the exception is being thrown and can’t seem to figure out how to get the thread to go away once the task is done running. Am I just missing something small?

Edit: I forgot to mention that the done() function in the background task is being called as well after the task is done.

Thanks,
Chris

Hello @chriskrozel

Let’s consider that the task is created in the following way:

private BackgroundTask<Integer, String> createTask() {
    return new BackgroundTask<Integer, String>(10L, this) {
        @Override
        public String run(TaskLifeCycle<Integer> taskLifeCycle) throws InterruptedException {
            Thread.sleep(5000L);
            return "Task finished!";
        }

        @Override
        public void done(String result) {
            // "done" is invoked in UI thread
            notifications.create(Notifications.NotificationType.TRAY)
                    .withCaption(result)
                    .show();
        }

        @Override
        public void canceled() {
            // "cancel" is also invoked in UI thread
            notifications.create(Notifications.NotificationType.TRAY)
                    .withCaption("Background task is canceled!")
                    .show();
        }
    };
}

To handle background task the BackgroundWorker bean is used, so we should inject it into screen controller:

@Inject
private BackgroundWorker backgroundWorker;

To be track current execution we should store BackgroundTaskHandler instance, so just add one more field:

private BackgroundTaskHandler<String> currentTaskHandler = null;

Now we can check if previous background task is not finished its execution, stop it and run new one:

@Subscribe("runTask")
public void onRunTaskClick(Button.ClickEvent event) {
    if (currentTaskHandler != null
            && currentTaskHandler.isAlive()) {
        // stop current execution 
        currentTaskHandler.cancel();
    }

    currentTaskHandler = backgroundWorker.handle(createTask());

    currentTaskHandler.execute();
}

Please check attached project for demo:

run-background-tasks.zip (69.8 KB)

Documentation: Background Tasks

Regards,
Daniil

1 Like

Hi Daniil,

Thanks for the reply!, this does work.

I do have one more question though. Creating a new task every time I want to run the task does create new threads still and leave them there after the task is finished. Is this okay? Would any issues occur if a large number of threads are created? I do know the threads go away eventually and aren’t doing anything once the task is finished but just wondering.

Thanks,
Chris

In general, everything will be fine if, in the long run, the threads finish their work. But it’s a bit dangerous to leave them without any control.