2010-11-12 2 views
2

Приложение Java WebStart, над которым я работаю, использует SWT для GUI, и я недавно понял небольшую, но раздражающую проблему. Когда я выбираю действие, которое использует FileDialog, т. Е. Сохраняет изображение, пользовательский интерфейс замерзает сразу после закрытия диалога. Изображение сохраняется и может быть открыто с помощью средства просмотра изображений по умолчанию без каких-либо проблем, но приложение не реагирует с этого момента, и я вынужден убить приложение.SWT зависает/зависает в Linux при развертывании в виде Java Web Start

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

Я попытался реплицировать проблему только в Windows, чтобы убедиться, что она отлично работает на Win 7. В качестве второй попытки устранения неполадок я попытался сохранить изображение из локальной версии приложения (другими словами, -JWS), и это отлично работает ...

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

Любые идеи?

UPDATE: Похоже, что проблема не только зависит от FileDialog, но и от любого графического взаимодействия с пользователем. Всякий раз, когда развертываются окна SWT, программа зависает с серым экраном, ПОСЛЕ любого действия, которое должно было быть сделано. Я скопировал код ниже, в этом конкретном примере, даже если я нажму «Отмена», приложение перестает реагировать на серый экран. Вот некоторые примеры кода:

public static boolean saveChangesBeforeDiscard(MyMain main) 
{ 
    if (main.isDirty()) 
    { 
     MessageBox messageBox = new MessageBox(
      main.getShell(), 
      SWT.ICON_WARNING | SWT.YES | SWT.NO | SWT.CANCEL); 

     messageBox.setMessage("Would you like to save the changes?"); 
     messageBox.setText(MyMain.TOOL_NAME); 
     int answer = messageBox.open(); 

     if (answer == SWT.YES) 
     { 
      SaveFileAction save = new SaveFileAction(main); 
      save.run(); 

      return save.isSaved(); 
     } 
     else if (answer == SWT.NO) 
     { 
      return true; 
     } 

     return false; 
    } 

    return true; 
} 

Update 2: Btw Я использую Sun JDK 1.6.0. Вот вывод команды Java -version:

ява версия "1.6.0_22" Java (TM) SE Runtime Environment (строительство 1.6.0_22-b04) Java HotSpot (TM) 64-разрядного сервера VM (построить 17.1-b03, смешанный режим)

+0

Какой JVM вы используете? –

+0

@Dave: только что добавлено в основной текст – posdef

+0

Вы указываете полные разрешения в политике безопасности веб-центра? – qualidafial

ответ

3

Если SaveFileAction.run() занимает много времени, это объясняет замораживание пользовательского интерфейса.

В SWT вы несете ответственность за запуск насоса для мероприятий. Обычно это выглядит примерно так:

while (!shell.isDisposed()) { 
    if (!display.readAndDispatch()) { 
    display.sleep(); 
    } 
} 

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

Если требуются длительные операции, рекомендуемая практика в SWT заключается в выполнении операции в рабочем потоке, при необходимости отправляющей асинхронные обновления в пользовательский интерфейс.

executor.execute(new Runnable() { 
    public void run() { 
    showStatusMessage("Saving "+filename+"..."); 

    SaveFileAction save = new SaveFileAction(main); 
    save.run(); 

    showStatusMessage("File "+filename+" saved.") 
    } 

    private void showStatusMessage(final String message) { 
    Display.getDefault().asyncExec(new Runnable() { 
     public void run() { 
     statusLine.setMessage(message); 
     } 
    }); 
    } 
}); 

This entry на SWT FAQ объясняет потоковую модель более подробно.

+0

Извините за очень поздний ответ, я работал над рукописью, когда пришел ваш ответ, и, конечно же, праздники ... В любом случае, я искренне благодарю вас за советы по управлению потоком/процессом с помощью SWT, однако ваша теория не " действительно объясняет, почему GUI замерзает, даже когда пользователь избегает каких-либо действий с помощью кнопки «Отмена». Другими словами, даже если никакое действие не выполняется после развертывания окна, графический интерфейс зависает. Если у вас есть какие-либо предложения по опробованию и сужению проблемы, я с радостью буду охарактеризовать код :) – posdef

+0

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

+0

Интересный момент, мне нужно немного вникать в него и попробовать немного. Кстати, есть ли у вас какие-либо идеи, почему это было бы проблемой для Linux, а не на системах Windows? – posdef

1

Существует ошибка в SWT, который вызывает это: here

Исправлена ​​ошибка недавно была решена - см ошибка для получения дополнительной информации.

+0

Благодарим за информацию, но она появляется как ошибка, упомянутая в ссылке, и предлагаемое там решение относится к eclipse, тогда как я не использую eclipse для сборки JWS. Более того, у меня не было проблем с средой Windows, в отличие от сообщенных комментариев в buginfo. У меня отсутствует какая-то связь между проблемами? – posdef

+0

Ошибка говорит о платформе как GTK. Кроме того, в то время как заголовок ссылается на плагин WebStart RCP, та же самая основная проблема вызывает замораживание любого приложения SWT/Linux/Webstart. Протестируйте сборку интеграции и посмотрите, решит ли она вашу проблему. – Vik

0

У меня была аналогичная проблема. Я решил это, запустив файл jnlp с IcedTea Java 6 Webstart (javaws) OpenJDK вместо Oracle javaws.

Смежные вопросы