Как остановить SwingWorker?

Как я могу остановить SwingWorker выполнение своей работы? Я знаю, что для этого есть cancel() метод, но максимум, что я мог сделать, это анонимно создать новый SwingWorker, который выполняет свою работу.

Вот код для справки:

public void mostrarResultado(final ResultSet resultado) {

    new SwingWorker<Void, Object[]>() {

        @Override
        public Void doInBackground() {

            // TODO: Process ResultSet and create Rows.  Call publish() for every N rows created.+
            DefaultTableModel modelo = new DefaultTableModel();
            jTableResultados.removeAll();
            int columnas;
            int res = 0;
            try {
                ResultSetMetaData metadata = resultado.getMetaData();
                columnas = metadata.getColumnCount();
                Object[] etiquetas = new Object[columnas];
                jProgressBar.setIndeterminate(true);
                for (int i = 0; i < columnas; i++) {
                    etiquetas[i] =
                            metadata.getColumnName(i + 1);
                }
                modelo.setColumnIdentifiers(etiquetas);
                jTableResultados.setModel(modelo);

                while (resultado.next() && !this.isCancelled()) {
                    res++;
                    Object fila[] = new Object[columnas];
                    for (int i = 0; i < columnas; i++) {
                        fila[i] = resultado.getObject(i + 1);
                    }
                    modelo.addRow(fila);
                    publish(fila);
                }
                jProgressBar.setIndeterminate(false);
                if (res == 0) {
                    JOptionPane.showMessageDialog(jPanelClientes.getParent(), "No se encontraron resultados con los criterios de búsqueda definidos", "Sin resultados", JOptionPane.INFORMATION_MESSAGE);
                }
            } catch (SQLException ex) {
                LOG.log(Level.SEVERE, "Excepcion: ", ex);
                JOptionPane.showMessageDialog(jPanelClientes.getParent(), "Error en al ejecutar la busqueda seleccionada", "Error", JOptionPane.ERROR_MESSAGE);
            }
            return null;
        }
    }.execute();
}

На самом деле работа выполнена хорошо и опубликована без проблем, но, учитывая, что я работаю с БД, может случиться так, что запрос будет иметь слишком много результатов, и время, затраченное на полную публикацию, займет время, поэтому пользователь должен иметь возможность отменить задачу и запустить новую.

Очевидно, что worker - это другой метод, чем событие кнопки отмены, поэтому я не смогу вызвать метод Worker cancel().

Пытался сделать рабочего атрибутом для класса, но безуспешно:

    public class myClass extends javax.swing.JFrame {
      private SwingWorker<Void, Object[]> tarea;

но потом, когда я пойду:

tarea = new SwingWorker<Void,Object[]>(){...} 

Я получаю несовместимые типы, обнаружен недействительный, требуемый SwingWorker, и у меня нет идей.

Какие-нибудь советы?

Спасибо


person Lowb    schedule 05.03.2012    source источник
comment
См. Также stackoverflow.com/questions / 6113944 /   -  person DNA    schedule 05.03.2012
comment
возможный дубликат Остановить / отменить ветку SwingWorker?   -  person DNA    schedule 05.03.2012
comment
Действительно, возможный дубликат, жаль, что поиск не выдал этот ответ: /   -  person Lowb    schedule 05.03.2012
comment
@Lowb возможный дубликат, да, мы не читатели мыслей, никто не знает, что происходит в остальной части вашего кода, потому что ваш код SwingWorkers неверен, пожалуйста, посмотрите мой ответ здесь, для получения лучшей помощи скорее отредактируйте свой пост с помощью SSCCE   -  person mKorbel    schedule 05.03.2012
comment
Я имел в виду, что не увидел этих ответов при поиске, и да, они решили мою проблему, поэтому я сказал, что это дубликат. Извините, если я недостаточно ясно понял.   -  person Lowb    schedule 05.03.2012
comment
Так что да, исправил проблему со ссылкой @DNA 2-й комментарий Спасибо !!   -  person Lowb    schedule 05.03.2012
comment
ваш фрагмент выглядит неправильно (при условии, что jtableResultados является JTable): вы не должны обращаться ни к какому компоненту представления, ни к его модели, ни к каким-либо другим его свойствам в doInBackground. Доступ к ним разрешен только в пользовательском методе процесса или в готовом виде.   -  person kleopatra    schedule 05.03.2012
comment
@kleopatra да, это JTable, но как еще мне разместить строки из запроса БД в JTable, если не в методе doInBackground?   -  person Lowb    schedule 05.03.2012
comment
в процессе (если вам нужны промежуточные обновления) и / или готово (если вас интересует только конечный результат)   -  person kleopatra    schedule 05.03.2012


Ответы (2)


Это не ответ на вопрос (как отменить, я думаю, это решено), а как отделить фоновую обработку от обновлений представления / модели. Схема псевдокода:

public static class MyDBWorker extends SwingWorker<Void, Object[]> {

    private JTable table;
    private DefaultTableModel model;
    private ResultSet resultado;

    public MyDBWorker(JTable table, ResultSet resultado) {
        this.table = table;
        this.resultado = resultado;
    }

    @Override
    protected Void doInBackground() throws Exception {
        ResultSetMetaData metadata = resultado.getMetaData();
        int columnas = metadata.getColumnCount();
        Object[] etiquetas = new Object[columnas];
        for (int i = 0; i < columnas; i++) {
            etiquetas[i] = metadata.getColumnName(i + 1);
        }
        publish(etiquetas);
        while (resultado.next() && !this.isCancelled()) {
            Object fila[] = new Object[columnas];
            for (int i = 0; i < columnas; i++) {
                fila[i] = resultado.getObject(i + 1);
            }
            publish(fila);
        }
        return null;
    }


    @Override
    protected void process(List<Object[]> chunks) {
        int startIndex = 0;
        // first chunk, set up a new model
        if (model == null) {
            model = new DefaultTableModel();
            model.setColumnIdentifiers(chunks.get(0));
            table.setModel(model);
            startIndex = 1;
        }
        for (int i = startIndex; i < chunks.size(); i++) {
            model.addRow(chunks.get(i));
        }
    }

    @Override
    protected void done() {
        // nothing to do, we were cancelled
        if (isCancelled()) return;
        // check for errors thrown in doInBackground
        try {
            get();
            // all was well in the background thread
            // check if there are any results
            if (table.getModel().getRowCount() == 0) {
                // show message
            }
        } catch (ExecutionException e) {
            // we get here if f.i. an SQLException is thrown
            // handle it as appropriate, f.i. inform user/logging system
        } catch (InterruptedException e) {
            // 
        }
    }

}

// use it
SwingWorker worker = new MyDBWorker(table, resultado);
PropertyChangeListener stateListener = new PropertyChangeListener() {

    @Override
    public void propertyChange(PropertyChangeEvent e) {
        if (e.getNewValue() == SwingWorker.StateValue.STARTED) {
            progressBar.setIndeterminate(true);
        }
        if (e.getNewValue() == SwingWorker.StateValue.DONE) {
            progressBar.setIndeterminate(false);
        }

    }

};
worker.addPropertyChangeListener(doneListener);
worker.execute();

Изменить

исправлена ​​ошибка в процессе: добавление строк в модель должно всегда начинаться с первого индекса пакета, кроме обработки заголовка.

person kleopatra    schedule 05.03.2012
comment
спасибо за подсказку @kleopatra. Думаю, вместо публикации (fila) я должен вызывать процесс (fila) для каждой строки, которую я хочу опубликовать? - person Lowb; 05.03.2012
comment
@Lowb, нет - единственное, что действительно впечатляет, - это четкое разделение потоков: некоторые методы предназначены для вызова в фоновом потоке (fi doInBackground, publish), в то время как другие гарантированно будут выполняться в EDT (процесс fi , сделано). Никогда не смешивайте методы одной группы с методами другой группы. - person kleopatra; 05.03.2012
comment
хммм, я не понимаю @kleopatra, когда тогда вызывается process ()? каково содержание кусков? как я могу определить, когда строки отображаются в пользовательском интерфейсе? слишком много вопросов, извините :( - person Lowb; 05.03.2012
comment
@Lowb просто вызывает публикацию в doInBackground всякий раз, когда вы хотите обновить пользовательский интерфейс. Фактическое обновление происходит в процессе, независимо от того, что происходит между публикацией - ›процесс полностью внутренен для рабочего и не находится под вашим контролем (и вы не хотите знать об этом :-) - person kleopatra; 05.03.2012
comment
хорошо, хорошо, теперь я понял, когда я вызываю publish (), программа выполняет некоторые действия и вызывает process (), и поэтому правильно? спасибо кстати !!! - person Lowb; 05.03.2012
comment
@kleopatra Я всегда там замечал (видел несколько раз), что после get (); следующая строка кода связана с блоком захвата - person mKorbel; 05.03.2012
comment
@kleopatra, это то же самое, что и раньше, я всегда начинал с 1, не так ли? - person Lowb; 09.03.2012
comment
@Lowb извините за путаницу: в методе процесса заполнение данных строки (в модели) должно начинаться с 1 , только если 0 соответствует заголовку, в противном случае должно начинаться с 0. Все в doInBackground просто отлично и без изменений - person kleopatra; 09.03.2012

1) никогда не создавайте / не воссоздайте

DefaultTableModel modelo = new DefaultTableModel();

2) пожалуйста, что

jTableResultados.removeAll();

JTable, AbstractTableModel, DefaultTableModel

3) ваш JProgressBar не может работать

jProgressBar.setIndeterminate(false);

4) оба связанных вопроса заставляют меня задуматься в связи с отменой SwingWorker's экземпляра

person mKorbel    schedule 05.03.2012
comment
1) как мне тогда определить модель таблицы? 2) это удаляет ранее показанные результаты в jTable, который показывает результаты для запроса BD 3) индикатор выполнения работает нормально. 4) это решило, да. - person Lowb; 05.03.2012