Как выяснить, когда я должен сделать вызов функции в потоке GUI - PullRequest
1 голос
/ 19 октября 2010

Как я могу узнать, должен ли я сделать вызов функции в потоке GUI.

if (SwingUtilities.isEventDispatchThread()) {
    // ...
} else {

    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            // ...
        }
    });
}

Например

// Should I call this within GUI thread?
jTable.getModel().setValueAt(...

Или

// Should I call this within GUI thread?
jComboBox.showPopup();

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

В настоящее время я занимаюсь If I am not sure, I will just call them in GUI thread

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

Ответы [ 3 ]

1 голос
/ 19 октября 2010

Если вам действительно нужна какая-то сверхобобщенная функция «вызовите как можно скорее», полезен такой помощник:

void invokeAsSoonAsPossible(Runnable action) {
    if (SwingUtilities.isEventDispatchThread())
        action.run();
    else SwingUtilities.invokeLater(action);
}

// Usage:
invokeAsSoonAsPossible(new Runnable(){
    @Override
    public void run() {
        jTable.getModel().setValueAt(...
    }
});

Но мой опыт подсказывает, что это гораздо лучшая стратегия для структурирования и документирования вашего кода, чтобы было легче отслеживать, что и где выполняется. Если у вас есть открытый метод в классе, который должен быть запущен в EDT, JavaDoc - хороший друг:

/**
 * Blah blah blah, describe the method's purpose.
 * <p>
 * <strong>Note:</strong> This method should always be 
 * invoked on the Swing event dispatch thread.
 */
public Pony calulateValue() {
    // go ahead and touch the components any way you please
}

Вы также можете добавить утверждение в методах только для EDT как вид исполняемой документации:

assert SwingUtilities.isEventDispatchThread();

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

0 голосов
/ 19 октября 2010

Почти все методы Swing должны выполняться в потоке пользовательского интерфейса. Есть несколько исключений (например, setMethods). Эти исключения описаны в документации по API (обычно говорится что-то вроде «этот метод является поточно-ориентированным»). Однако общее правило таково, что все обновления GUI должны выполняться в потоке пользовательского интерфейса.


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

Однако, если вы иногда вызываете код из собственных потоков, а иногда из потока пользовательского интерфейса, вы можете, как показано в своем вопросе, определить, находитесь ли вы в потоке пользовательского интерфейса, вызвав EventQueue.isDispatchThread().

Я бы поместил код для выполнения в отдельный метод, updateGuiComponent(...) и сделал бы

if (EventQueue.isDispatchThread())
    updateGuiComponent(...);
else
    SwingUtilities.invokeLater(new Runnable() {          // or invokeAndWait
        public void run() { updateGuiComponent(...); }
    });
0 голосов
/ 19 октября 2010

На самом деле

if (SwingUtilities.isEventDispatchThread()) {
  // just do it, you're already in EDT
} else {
  SwingUtilities.invokeLater(new Runnable() {
    @Override
    public void run() {
        // ...
    }
  });
}

Весь код, который включает компоненты / классы Swing или AWT, должен выполняться в EDT, т.е. используя SwingUtilities.invokeLater(Runnable) помощник.

Вы можете настроить приложение, используя Substance Look & Feel для тестирования. Выдает исключение, если код, связанный с пользовательским интерфейсом, выполняется за пределами EDT.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...