0

I have a button that when clicked needs to spawn a Dialog with a ProgressBar to track task completion of a CompletionService. Before Marking this as duplicate, I do not believe this is an EDT problem because of the separate threading with the ProgressBarRunnable.

Below is the Code for the button click and associated worker:

        public static class WorkerRunnable implements Runnable {

        int taskCards;
        TaskManagerInterface ti;
        CompletionService ecs;
        PropertyChangeSupport pcs;

        public WorkerRunnable(int taskCards, TaskManagerInterface ti, CompletionService ecs, PropertyChangeSupport pcs) {
            this.taskCards = taskCards;
            this.ti = ti;
            this.ecs = ecs;
            this.pcs = pcs;
        }

        @Override
        public void run() {
            for (int i2 = 0; i2 < taskCards; i2++) {
                System.out.println("task=" + i2 + " of " + taskCards);
                try {
                    Future<Object> take = ecs.take();
                    TaskCard get = (TaskCard) take.get();
                    ti.deployTask(get);
                    Thread.sleep(1000);
                    pcs.firePropertyChange(ProgressBarUI.PROGRESS, taskCards, i2);
                } catch (InterruptedException ex) {
                    System.out.println("EXCEPTION!");
                    Exceptions.printStackTrace(ex);
                } catch (ExecutionException ex) {
                    Exceptions.printStackTrace(ex);
                }

            }
        }

    }

    @Override
    public void actionPerformed(ActionEvent e) {

        ExecutorService pool = Executors.newFixedThreadPool(5);
        CompletionService<Object> ecs = new ExecutorCompletionService<>(pool);
        ArrayList<TaskCard> taskCards = ti.getTaskCards();
        Iterator<TaskCard> i = taskCards.iterator();
        ProgressBarUI pb = new ProgressBarUI(dialog, "Submitting Tasks", true);
        pcs.addPropertyChangeListener(pb);

        while (i.hasNext()) {
            TaskCard tc = i.next();
            ecs.submit(new SubmitCallable(ti, ci, tc));
        }
        SwingUtilities.invokeLater(new WorkerRunnable(taskCards.size(), ti, ecs, pcs));
        pb.setLocationRelativeTo(dialog);
        pb.setVisible(true);

        System.out.println("Done!");
    }
CoupFlu
  • 311
  • 4
  • 20
  • 1
    Sorry, but this sort of question has been asked so many times it's ridiculous. Have you searched on it? It's all about Swing threading. – Hovercraft Full Of Eels Jul 21 '16 at 17:43
  • Bottom line: long running code goes in a background thread, and Swing calls need to be queued onto the Swing thread. – Hovercraft Full Of Eels Jul 21 '16 at 17:45
  • You need to make your `get()` calls in a background thread and then update the progress bar from the Swing thread. – Hovercraft Full Of Eels Jul 21 '16 at 17:46
  • I am using the ProgressBarRunnable for the swing component, is this not correct? – CoupFlu Jul 21 '16 at 17:47
  • I have no idea -- what is this ProgressBarRunnable? And regardless, your above code is going to freeze your application because it's called on the EDT since it's called from an ActionListener, and the for loop that calls `get()` on the Futures will block all since `get()` is a blocking call. – Hovercraft Full Of Eels Jul 21 '16 at 17:51
  • `" Before Marking this as duplicate, I do not believe this is an EDT problem because of the separate threading with the ProgressBarRunnable."` -- re-read my comment above. – Hovercraft Full Of Eels Jul 21 '16 at 17:52
  • ProgressBarRunnable is a Runnable wrapper that shows the ProgressBar. It is my understanding that this will conform to updating the UI from the EDT. – CoupFlu Jul 21 '16 at 17:53
  • This class is not part of core Java, so I cannot comment on it, but regardless of what it is or what it does, your above code blocks the EDT, pure and simple. End of discussion. – Hovercraft Full Of Eels Jul 21 '16 at 17:54
  • OK, I've seen your newly posted code and the run method involves itself only with progress bar creation. It has no relevance to your problem above. – Hovercraft Full Of Eels Jul 21 '16 at 17:55
  • To solve, put the for loop in a SwingWorker or a background thread, and update the progress bar from the EDT either with the worker's publish/process or with your directly queuing the request on the EDT. – Hovercraft Full Of Eels Jul 21 '16 at 17:57
  • My question is about the display of the ProgressBarUI, not the update of the progress bar. The progressbar is updating just fine. The problem is that the ProgressBarUI is showing up after the Executor is complete. The solution posted seems to be related to EDT issues. I don't believe I'm having those here. – CoupFlu Jul 21 '16 at 17:58
  • If the EDT is blocked, **nothing** will display. Believe what you want, but a simple test is to fix the for loop and see what happens. – Hovercraft Full Of Eels Jul 21 '16 at 18:02
  • Hang on, i'm working on it with your solution. – CoupFlu Jul 21 '16 at 18:04
  • Ok, I updated with the suggested changes, but now the progress bar doesn't update. I'm performing the update via a PropertyChangeListener in the ProgressBarUI. – CoupFlu Jul 21 '16 at 18:21
  • [pastebin](http://pastebin.com/5Z6CKULX) – Hovercraft Full Of Eels Jul 21 '16 at 18:32
  • You are the man. Is there prebuilt implementation of a progressbar with ECS that does this same thing though? Seems like that would be pretty handy. – CoupFlu Jul 21 '16 at 18:48
  • Post your code and I'll vote it as the answer. Thanks for the help. – CoupFlu Jul 21 '16 at 20:25
  • I can't because I've already closed your question as a duplicate. Again it is no different from all the other Swing threading problem questions out there. – Hovercraft Full Of Eels Jul 21 '16 at 20:34

0 Answers0