Предотвратите Swing GUI, запирающийся во время фоновой задачи

Убедитесь, что в каждом файле имеется только один подкласс XCTestCase. Вы хотите, чтобы имена файлов и классов совпадали.

По моему опыту, даже если у вас работают тесты пользовательского интерфейса, если вы добавите новый подкласс вашего рабочего подкласса XCTestCase в тот же файл, кнопка записи будет отключена (хотя все другие пользовательские интерфейсы тестирования будут продолжать работать).

11
задан Andrew Thompson 30 January 2013 в 12:34
поделиться

5 ответов

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

Что вам нужно сделать, так это поместить длительную задачу в другой поток.

Некоторые распространенные способы сделать это - использовать таймеры или SwingWorker .

В учебных пособиях по Java содержится много информации об этих вещах в уроках по параллелизму.

Чтобы убедиться в этом, первая задача завершается раньше второй, просто поместите их в один поток. Таким образом, вам не придется беспокоиться о том, чтобы правильно синхронизировать два разных потока.

Вот пример реализации SwingWorker Для вашего случая:

public class YourTaskSwingWorkerSwingWorker extends SwingWorker<List<Object>, Void> {
    private List<Object> list
    public YourClassSwingWorker(List<Object> theOriginalList){
        list = theOriginalList;
    }

    @Override
    public List<Object> doInBackground() {
        // Do the first opperation on the list
        // Do the second opperation on the list

        return list;
    }

    @Override
    public void done() {
        // Update the GUI with the updated list.
    }
}

Чтобы использовать этот код, когда запускается событие для изменения списка, создайте новый SwingWorker и скажите ему, чтобы он запустился.

18
ответ дан 3 December 2019 в 04:14
поделиться

Похоже, проблема в том, что вы ждете завершения потоков изнутри графического интерфейса. нить. Ваш поток графического интерфейса не должен ждать этих потоков, вместо этого вы должны заставить рабочие потоки вызывать какой-либо метод в потоке графического интерфейса, который устанавливает флаг. Когда оба флага установлены, вы знаете, что оба потока завершены, и можете построить график.

1
ответ дан 3 December 2019 в 04:14
поделиться

Я не могу говорить с моделью потоковой передачи Swing, но:

Я тоже должен выполнить два этапа обработки по порядку, так что лучший способ обеспечить второй этап дождался первого?

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

0
ответ дан 3 December 2019 в 04:14
поделиться

Вы неправильно возвращаете качающуюся нить. Я понимаю, что вы используете callable / runnable, но я предполагаю, что вы делаете это неправильно (хотя вы не опубликовали достаточно кода, чтобы знать наверняка).

Основная структура будет такой:

swingMethod() { // Okay, this is a button callback, we now own the swing thread
    Thread t=new Thread(new ActuallyDoStuff());
    t.start();
}

public class ActuallyDoStuff() implements Runnable {
    public void run() {
        // this is where you actually do the work
    }
}

Это просто отключено в верхней части моей головы, но я предполагаю, что вы либо не выполняете thread.start, а вместо этого вызываете метод run напрямую, либо вы делаете что-то еще в первом методе, который блокирует его (например, thread.join ). Ни один из них не освободил бы нить качания. Первый метод ДОЛЖЕН возвращаться быстро, метод run () может длиться сколько угодно времени.

Если вы выполняете thread.join в первом методе, то поток НЕ возвращается в систему!

Изменить: (На самом деле второе редактирование) Я думаю, если говорить о проблеме, которую вы действительно чувствуете - вы, возможно, захотите больше думать в терминах системы модель / представление / контроллер. Код, который вы пишете, является контроллером (представление обычно считается компонентами на экране - представление / контроллер обычно очень жестко связаны).

Когда ваш контроллер получает событие, он должен передать работу ваша модель. Вид тогда не в картинке. Он не ждет модель, это просто сделано.

Когда ваша модель закончена, она должна сказать контроллеру сделать что-то еще. Это делается с помощью одного из методов вызова. Это передает управление обратно контроллеру, и вы продолжаете свой веселый путь. Если вы думаете об этом таким образом, разделение контроля и намеренная передача его туда и обратно не кажется таким громоздким, и на самом деле это очень распространено, чтобы сделать это таким образом.

6
ответ дан 3 December 2019 в 04:14
поделиться

Решением моей проблемы стало сочетание ответов jjnguy и Билла К., так что большое спасибо за них. Мне нужно было использовать потоки в SwingWorker следующим образом:

public class Worker extends SwingWorker<Void, Void>   
{  
    private List<Object> list;  
    public YourClassSwingWorker(List<Object> theOriginalList){  
        list = theOriginalList;  
    }

    @Override
    public List<Object> doInBackground() {
        Thread t = new Thread(new ProcessorThread(list));  
        t.start();
    }

    @Override
    public void done() {
        // draw graph on GUI
    }
}  
class ProcessorThread implements Runnable {  
    //do lots of IO stuff  
    Thread t2 = new Thread(new SecondProcess());
    t2.start();  
}

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

0
ответ дан 3 December 2019 в 04:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: