2016-01-21 6 views
1

Это в контексте модульного тестирования (как это бывает).Можно ли вызвать Future.get() в потоке, отличном от EDT, из потока EDT?

В конце теста, независимо от результата, я хочу, чтобы код проверял наличие (видимость) диалогового окна JFileChooser ... и, если видимо, отмените его.

Существуют разные способы отклонения диалога, конечно, но для подражания действию человека (и, например, для примера такого вопроса, который касается меня), я выбираю использовать java.awt.Robot. Методы последнего должны выполняться в потоке, отличном от EDT.

На самом деле я продлил Robot включать удобный метод, называемый type_input, так

robot.type_input(KeyEvent.VK_F4, KeyEvent.VK_ALT) 

прессы первый Alt, затем F4, затем отпускает F4, а затем Alt: как человек отклонении окно/диалогового окна.

Я отправляю Runnable с использованием invokeAndWait, потому что я не хочу, чтобы код запускался до следующего теста, пока это диалоговое окно не было отклонено. Я должен проверить видимость и сосредоточиться в EDT. Но метод Робота должен, как я сказал, работать в не-EDT.

Есть ли какие-либо потенциальные проблемы с ходом get() вот так в EDT? Может ли это привести к невосприимчивости к графическому интерфейсу? Дело в том, что я слышал, что каркас способен «запускать новый насос EDT» при определенных условиях. Я должен признаться, что это один из аспектов EDT связанных с вопросами, которые я чувствую, что я знаю, как минимум о ...

import java.awt.EventQueue; 
import java.awt.Robot; 
import java.awt.event.KeyEvent; 
import java.lang.reflect.InvocationTargetException; 
import java.util.concurrent.BlockingQueue; 
import java.util.concurrent.Callable; 
import java.util.concurrent.ExecutionException; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.Future; 
import java.util.concurrent.ThreadPoolExecutor; 
import javax.swing.JDialog; 
import javax.swing.JFileChooser; 
import javax.swing.JFrame; 

class MainFrame extends JFrame { 
    JFileChooser update_target_file_chooser; 
    JDialog file_chooser_dlg; 

    // ... rest of class 

} 

public class ThreadWithinThread { 

    public static void main(String[] args) throws InvocationTargetException, InterruptedException { 

     final ExecutorService thread_pool_exec_serv = Executors.newFixedThreadPool(5); 

     class DismissDlg implements Runnable { 
      MainFrame main_frame; 
      Robot robot; 

      @Override 
      public void run() { 
       boolean focus_on_dlg = main_frame.file_chooser_dlg.hasFocus(); 
       if(main_frame.file_chooser_dlg.isVisible()){ 
        if(! focus_on_dlg){ 
         main_frame.file_chooser_dlg.requestFocus(); 
        } 
        class AltF4 implements Callable<Void>{ 
         public Void call(){ 
          return robot.type_input(KeyEvent.VK_F4, KeyEvent.VK_ALT); 
         } 
        } 
        Future<Void> future_result = thread_pool_exec_serv.submit(new AltF4()); 
        try { 
         // this is the line I'm worried about 
         future_result.get(); 
        } catch (InterruptedException | ExecutionException e) { 
         e.printStackTrace(); 
        } 
       } 
      } 
     } 
     EventQueue.invokeAndWait(new DismissDlg()); 
    } 

} 

позже

Как я уже говорил в моих ответах, это не является конкретным практическим решением для рассматриваемого случая: я действительно пытаюсь понять, запускается ли еще один EDT «event pump» с Future.get(), блокирующим EDT. Как я уже сказал, мне трудно понять весь этот аспект. Мое использование статических методов JOptionPane (которые должны быть запущены в EDT, см. Сообщения в SO ad nauseam) показывает мне, что эти методы (которые блокируют EDT!) Фактически не мешают работе графического интерфейса (NB не следует путать с тем, являются ли эти JOptionPane s, а точнее их JDialog s, модальными или немодальными).

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

+0

Как трудно бы это, чтобы получить ссылку на JFileCho oser и call isVisible, а затем вызвать setVisible (false)? – Bill

+0

@Bill Спасибо - на самом деле я в основном обеспокоен тем, использует ли Future.get() другой «event pump», начиная с появления другого события EDT. Дело не в том, что у меня возникают практические трудности с поиском «определенного решения». –

+0

Была просто мыслью. Возможно, вы не можете получить доступ к диалоговому окну, но, возможно, это возможно. Иногда мы становимся настолько увлеченными более сложными ответами, что забываем про простые вещи. – Bill

ответ

2

Так, из JavaDocs

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

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

А, а что делать?Вы можете использовать SwingWorker вместо этого, который внутренне использует собственную ExecutorService или submit работника к своим собственным ExecutorService (SwingWorker орудий Runnable), то вы должны быть в состоянии использовать PropertyChangeListener для мониторинга состояния SwingWorker и когда это DONE, вы может получить значение от его get метод без блокировки

+0

Спасибо ... да, я знаю все о SwingWorker и использую его все время. Основной вопрос моего вопроса заключается в том, чтобы понять, будет ли использование функции Future.get() в результате запуска другого «события-насоса», если возникает другое событие EDT, когда get() блокирует EDT ... –

+1

Не уверен, что я понимаю, что вы означает, что 'Future # get' будет блокироваться до тех пор, пока' Callable' не вернет результат или 'Exception', что означает, что если вы вызываете его из контекста EDT, вы предотвратите его от обработки любых новых событий до тех пор, пока он не будет разблокирован, и метод вернется – MadProgrammer

+0

* «Как я уже сказал, мне трудно понять весь этот аспект. Мое использование статических методов JOptionPane ... демонстрирует мне, что эти методы (которые блокируют EDT!) На самом деле не препятствуют функционированию графического интерфейса», * - Модальные диалоги работают, перехватывая процесс диспетчеризации событий, позволяя обрабатывать и отправлять события, но позволяя им «блокировать» выполнение текущего потока ... да, у меня болит голова до – MadProgrammer

0

Выполните необходимые действия на EDT, и сигнализировать тест нить необходима ли дополнительная стадия:

class PrepDlgDismiss implements Runnable { 
    boolean file_chooser_visible; 
    @Override 
    public void run() { 
    boolean focus_on_dlg = main_frame.file_chooser_dlg.hasFocus(); 
    if(main_frame.file_chooser_dlg.isVisible()){ 
     file_chooser_visible = true; 
     if(! focus_on_dlg){ 
     main_frame.file_chooser_dlg.requestFocus(); 
     } 
    } 
    } 
} 
PrepDlgDismiss task = new PrepDlgDismiss(); 
EventQueue.invokeAndWait(task); 
if(task.file_chooser_visible){ 
    robot.type_input(KeyEvent.VK_F4, KeyEvent.VK_ALT); 
} 
+0

Спасибо ... Это практический ответ, который «реорганизует» вопрос, хотя я бы сказал, что из параллелизма PoV не очень-то желательно «сохранить» статус видимости, как этот. Но главное в моем вопросе заключается в том, чтобы понять, будет ли использование функции Future.get() в результате запуска другого «события-насоса», если возникает другое событие EDT, когда get() блокирует EDT ... –

+0

@mikerodent беспокойство относительно статуса видимости от параллельного POV? Несмотря на то, что это не документировано авторитетно, между действиями в задаче, выполняемой 'invokeAndWait()' и возвратом 'invokeAndWait()', происходит взаимосвязь между * actions-before *. Даже с этой гарантией * де-факто вы все еще чувствуете дискомфорт? Если это так, вы определенно не должны зависеть от поведения, которое еще менее гарантировано, например, нового насоса, запускающегося, когда EDT заблокирован. – erickson

+0

На самом деле, прежде всего, я пытаюсь понять, * ли * насос событий входит в игру в кругах, которые я описал: я не зависим от этого ... Я хочу понять! Моя точка зрения о «видимом» статусе здесь просто очень идиотская, что между окончанием 'invokeAndWait' и запуском команды' robot.type_input' какой-то другой бит кода мог бы отклонить диалог. . И этот набор роботов Alt-F4 может (например) заставлять что-то закрывать ... Это чистая совпадение с моей стороны. –