SwingWorker публикует sh () и обрабатывает (список) не по порядку после модального диалога - PullRequest
1 голос
/ 27 апреля 2020

В сложном приложении Java я расширяю SwingWorker, чтобы я мог обрабатывать чтение из сокета в фоновом режиме. Сокет предоставляет много данных, необходимых для обновления GUI.

Существует особая оговорка - сервер, который пишет в сокет, записывает вещи в совершенно определенном порядке, на который клиент полагается. Думайте об этом как об отправке определений терминов, а затем об использовании терминов. Если приложение не получает сначала определения, оно вылетает или отображает неверные данные. Не проблема, потому что сервер старается сделать все правильно, а сокет IS TCP, поэтому я получаю доставку в порядке. Это просто: я читаю из сокета в своей функции Worker.doInBackground, анализирую ее и вызываю publi sh (). В Worker.process (List) я перебираю список по порядку, обрабатывая то, что дал мне сокет. Все хорошо.

Все хорошо, если только сервер не отправляет что-то, что убеждает клиента всплыть диалоговое окно Модальное, что может произойти на ранних этапах перед отправкой. Когда окно модели запущено, фоновый поток продолжает читать сокет и вызывает publi sh (), что ожидается. Но worket.process (List) (который, как вы помните, является кодом, который выдает модальное диалоговое окно) начинает вызываться с вещами, которые дико вышли из строя. Скорее всего, он все еще находится в середине обработки последнего Списка, который ему был передан, и вызывался рекурсивно при любой обработке события модульной коробкой.

Мои заметки говорят, что можно делать GUI вещи, и только в, процесс (Список). Я предполагаю, что небезопасно делать GUI вещи в doInBackground (). Так что появление диалогового окна, я полагаю, должно происходить в процессе (Список).

Есть ли способ указать диалоговому окну прекратить вызывать doInBackground () или process ()? Я не хочу или не нужно ничего запускать, пока это диалоговое окно не будет закрыто. Есть ли более умный способ сделать то, что мне нужно? Сервер может свободно отправлять новые материалы в любое время, и порядок всегда будет иметь значение, поэтому я не вижу, когда будет безопасно устанавливать диалоговое окно.

Я пытался синхронизировать, удерживая заблокировать, когда открыто диалоговое окно, и doInBackground ждет объекта блокировки прямо перед вызовом publi sh (). Никаких кубиков - они, вероятно, выполняются одним и тем же потоком, а java блокировки являются рекурсивными. (И, может быть, если бы не диалоговое окно зависало.)

Я могу подумать о возможном неуклюжем обходном пути. Я мог бы пометить порядок вещей, поступающих в doInbackground () с порядковым номером, и в процессе) Я мог бы переиздать sh все, что я получу с порядковым номером, который неожиданно слишком велик. Но тогда я могу оказаться в узком l oop, пока диалоговое окно не будет закрыто («Пункт 1129 слишком высок. Republi sh. Пункт 1129 слишком высок. Republi sh ...»)

Какой правильный путь?

1 Ответ

0 голосов
/ 27 апреля 2020

Я не уверен, что понял, что вы спрашиваете на 100% (дайте мне знать, если мой ответ "offtopi c"), но я остановлюсь на этой части:

Is Есть ли способ сказать диалоговое окно прекратить вызывать doInBackground () или process ()? Я не хочу или не нужно ничего запускать, пока это диалоговое окно не будет закрыто.

Использование переменной блокировки - способ достижения этого. Смотрите мой пример. Комментарии внутри кода.

public class Worker extends SwingWorker<Void, String> {
    private JDialog dialog;

    public Worker() {
        dialog = new JDialog();
        dialog.setModal(true);
        dialog.setLocationByPlatform(true);

        //Plays no role but since there is no frame (icon in task bar)
        //you might not be able to terminate the program
        dialog.setAlwaysOnTop(true);
    }

    @Override
    protected Void doInBackground() throws Exception {
        int times = 0;
        while (true) { //Worker runs forever

            //If dialog is visible, just wait it until it is closed
            if (dialog.isVisible()) { //or dialog.isDisplayable()
                Thread.sleep(10); //Rest cpu
                continue;
            }
            //Here you read the data from server and you publish things to GUI - "process" method
            if (times == 5)
                publish("dialog");
            else if (times == 10)
                publish("exit");
            else
                publish("chunk");
            times++;
            Thread.sleep(500);
        }
    }

    @Override
    protected void process(List<String> chunks) {
        String chunk = chunks.get(0);
        System.out.println("Processing....:" + chunk);

        //A dialog requested
        if ("dialog".equals(chunk)) {
            dialog.setVisible(true);
            System.out.println("Dialog closed");
        }
        //Exit requested
        else if ("exit".equals(chunk)) {
            System.out.println("Ran process 10 times, exiting....");
            System.exit(1);
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new Worker().execute());
    }
}
...