Найти нарушения потока рассылки событий - PullRequest
4 голосов
/ 16 декабря 2011

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

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

Какие подходы люди обычно используют с этим

Ответы [ 4 ]

5 голосов
/ 16 декабря 2011

Один из подходов - установить собственный менеджер перерисовок, который обнаруживает и регистрирует, когда рисование выполняется в потоке, отличном от EDT. Мы используем этот подход в нашем проекте, адаптированном из следующего блога: http://weblogs.java.net/blog/alexfromsun/archive/2006/02/debugging_swing.html. Это не обнаружит все классы нарушений потока EDT, но оно определенно намного лучше, чем ничего.

Обновление:

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

import javax.swing.JComponent;
import javax.swing.RepaintManager;
import javax.swing.SwingUtilities;
import org.apache.log4j.Logger;
import sun.awt.AppContext;

public class DetectEdtViolationRepaintManager extends RepaintManager {

  private static final Logger LOGGER = Logger.getLogger(
    DetectEdtViolationRepaintManager.class);

  /**
   * Used to ensure we only print a stack trace once per abusing thread.  May
   * be null if the option is disabled.
   */
  private ThreadLocal alreadyWarnedLocal;

  /**
   * Installs a new instance of DetectEdtViolationRepaintManager which does not
   * warn repeatedly, as the current repaint manager.
   */
  public static void install() {
    install(false);
  }

  /**
   * Installs a new instance of DetectEdtViolationRepaintManager as the current
   * repaint manager.
   * @param warnRepeatedly whether multiple warnings should be logged for each
   *        violating thread
   */
  public static void install(boolean warnRepeatedly) {
    AppContext.getAppContext().put(RepaintManager.class, 
      new DetectEdtViolationRepaintManager(warnRepeatedly));
    LOGGER.info("Installed new DetectEdtViolationRepaintManager");
  }

  /**
   * Creates a new instance of DetectEdtViolationRepaintManager.
   * @param warnRepeatedly whether multiple warnings should be logged for each
   *        violating thread
   */
  private DetectEdtViolationRepaintManager(boolean warnRepeatedly) {
    if (!warnRepeatedly) {
      this.alreadyWarnedLocal = new ThreadLocal();
    }
  }

  /**
   * {@inheritDoc}
   */
  public synchronized void addInvalidComponent(JComponent component) {
    checkThreadViolations();
    super.addInvalidComponent(component);
  }

  /**
   * {@inheritDoc}
   */
  public synchronized void addDirtyRegion(JComponent component, int x, int y, 
    int w, int h) {
    checkThreadViolations();
    super.addDirtyRegion(component, x, y, w, h);
  }

  /**
   * Checks if the calling thread is called in the event dispatch thread.
   * If not an exception will be printed to the console.
   */
  private void checkThreadViolations() {
    if (alreadyWarnedLocal != null && Boolean.TRUE.equals(alreadyWarnedLocal.get())) {
      return;
    }
    if (!SwingUtilities.isEventDispatchThread()) {
      if (alreadyWarnedLocal != null) {
        alreadyWarnedLocal.set(Boolean.TRUE);
      }
      LOGGER.warn("painting on non-EDT thread", new Exception());
    }
  }
}
4 голосов
/ 16 декабря 2011

Я просто стараюсь быть осторожным, сам. Но вы можете установить код, чтобы проверить, выполняется ли данный фрагмент кода в потоке диспетчеризации с помощью SwingUtilities.isEventDispatchThread (), и делать то, что вам нравится, если это не так (или если это так).

3 голосов
/ 16 декабря 2011

Внешний вид вещества включает в себя автоматическую проверку нарушений EDT во время выполнения . Это может помочь выявить нарушения EDT при тестировании. Он выдает исключение IllegalStateException при обнаружении нарушения. Это хорошо для тестирования.

0 голосов
/ 17 декабря 2013

Модуль свинга Fest также включает в себя Проверку нарушения EDT , которую вы можете установить, которая выдает исключение при обнаружении нарушения.

...