Как правильно обновить индикатор выполнения для операции неизвестной продолжительности в мастере Eclipse? - PullRequest
4 голосов
/ 03 октября 2011

Я реализовал мастер для моего плагина Eclipse, показывая несколько страниц.Одна из этих страниц требует некоторой длительной инициализации, то есть она состоит из таблицы SWT, которая должна быть заполнена информацией, поступающей из внешнего источника.Этот источник необходимо сначала активировать (один единственный вызов метода, который возвращается через пару секунд - я не могу заранее знать, сколько именно времени это займет), прежде чем его можно будет использовать в качестве входных данных для средства просмотра таблиц.Эта инициализация в настоящее время выполняется поставщиком модели таблицы, когда ему необходимо получить доступ к внешнему источнику в первый раз.

Поэтому, когда я вхожу на страницу мастера, я хотел бы показать фиктивную шкалу прогресса, которая просто считаетна некоторое время.Мой подход заключался в следующем, но, к сожалению, он не работает вообще:

private void initViewer() {
    IRunnableWithProgress runnable = new IRunnableWithProgress() { // needed to embed long running operation into the wizard page

        @Override
        public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
            SubMonitor progress = SubMonitor.convert(monitor);

            Thread thread = new Thread() {
                @Override
                public void run() {
                    Display.getDefault().syncExec(new Runnable() {
                        public void run() {
                            viewer.setInput(ResourcesPlugin.getWorkspace().getRoot()); // this will make the table provider initialize the external source.
                        }
                    });
                }
            };

            thread.start();

            while(thread.isAlive()) {
                progress.setWorkRemaining(10000);
                progress.worked(1);
            }

            progress.done();
        }

    };

    try {
        getContainer().run(false, false, runnable);
    } catch(Exception e) {
        throw new Exception("Could not access data store", e);
    }
}

Этот метод затем вызывается при вызове метода setVisible () - страницы мастера и должен через несколько секунд установитьвклад зрителя.Это, однако, никогда не происходит, потому что самый внутренний метод run () никогда не выполняется.

Любые подсказки о том, как обращаться с долгосрочными (где точная оценка недоступна) инициализациями в мастерах Eclipseбыл бы очень признателен!

Ответы [ 2 ]

1 голос
/ 03 октября 2011

Ниже приведен простой пример использования IRunnableWithProgress вместе с ProgressMonitorDialog для выполнения задачи с неизвестным количеством. Для начала имейте реализацию IRunnableWithProgress, из которой выполняется фактическая задача. Эта реализация может быть внутренним классом.

public class MyRunnableWithProgress implements IRunnableWithProgress {
    private String _fileName;

    public MyRunnableWithProgress(String fileName) {
        _fileName = fileName;
    }

    @Override
    public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
        int totalUnitsOfWork = IProgressMonitor.UNKNOWN;
        monitor.beginTask("Performing read. Please wait...", totalUnitsOfWork);
        performRead(_fileName, monitor); // This only performs the tasks
        monitor.done();
    }
}

Теперь можно создать общую реализацию для ProgressMonitorDialog , как показано ниже, которая может использоваться для других мест, где требуется диалоговое окно монитора прогресса.

public class MyProgressMonitorDialog extends ProgressMonitorDialog {

    private boolean cancellable;

    public MyProgressMonitorDialog(Shell parent, boolean cancellable) {
        super(parent);
        this.cancellable = cancellable;
    }

    @Override
    public Composite createDialogArea(Composite parent) {
        Composite container = (Composite) super.createDialogArea(parent);
        setCancelable(cancellable);
        return container;
    }
}

Получив требуемую реализацию, можно вызвать задачу, как показано ниже, для ее обработки с помощью диалогового окна прогресса.

boolean cancellable = false;
IRunnableWithProgress myRunnable  = new MyRunnableWithProgress(receivedFileName);
ProgressMonitorDialog progressMonitorDialog = new MyProgressMonitorDialog(getShell(), cancellable);

try {
    progressMonitorDialog.run(true, true, myRunnable);
} catch (InvocationTargetException e) {
    // Catch in your best way
    throw new RuntimeException(e);
} catch (InterruptedException e) {
    //Catch in your best way
    Thread.currentThread().interrupt();
}

Надеюсь, это поможет!

1 голос
/ 03 октября 2011

Я предполагаю, что причина, по которой он «не работает», заключается в том, что подготовка ввода выполняется в потоке пользовательского интерфейса, что означает, что индикатор выполнения не может быть обновлен.Лучший подход заключается в том, чтобы подготовить ввод заранее и только после этого установить ввод для зрителя.

...