|
|
|
Вопрос по javafx.concurrent
|
|||
|---|---|---|---|
|
#18+
Пара вопросов по сабжу: 1. В Task-потоке делается запрос к mysql и если в запросе есть ошибка, то поток exception'ов не выкидывает и соответственно висит. Конструкция Код: java 1. возвращает "java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-4", что логично и мало чего дает. Если запрос к БД поместить в Platform.runLater(() -> { }); то проблема решается, но тогда теряется сам смысл выноса запроса в поток, т.к. выполняется он будет в "основном" потоке, верно ? 2. Если правильно понял, то с результатами работы потока мы работаем с помощью setOnSucceeded,setOnFailed и т.д. А если потоков 5, 10, 50 и к каждому потребуется прописать хотя бы два вышеназванных события, то кода получится просто куча. Это как-то можно сократить ? Собственно больше волнует первый вопрос. Заранее благодарю! Ниже простой пример использования потока для проверки аутентификации, если кто-то прокомментирует код, так же буду очень благодарен! Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.05.2014, 19:09 |
|
||
|
Вопрос по javafx.concurrent
|
|||
|---|---|---|---|
|
#18+
korshun, особо не вдумываясь, может так: Код: java 1. 2. 3. 4. 5. 6. 7. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.05.2014, 11:48 |
|
||
|
Вопрос по javafx.concurrent
|
|||
|---|---|---|---|
|
#18+
korshun, сорри, не внимательно прочитал вопрос ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.05.2014, 11:49 |
|
||
|
Вопрос по javafx.concurrent
|
|||
|---|---|---|---|
|
#18+
korshun1. В Task-потоке делается запрос к mysql и если в запросе есть ошибка, то поток exception'ов не выкидывает и соответственно висит. "Висит" здесь очень не точный и не корректный термин для описания того что на самом деле происходит. korshunКонструкция Код: java 1. возвращает "java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-4", что логично и мало чего дает. Чет не понял. А зачем вы биндинг вызываете асинхронно в своих потоках? Биндить надо в начале инициализации. korshunЕсли запрос к БД поместить в Platform.runLater(() -> { }); то проблема решается, но тогда теряется сам смысл выноса запроса в поток, т.к. выполняется он будет в "основном" потоке, верно ? Нет, не верно. Не понятно как IllegalStateException связан с вашим кодом. У вас loginIn тоже в каком-то странном потоке выполняется? Или как? Обратите внимание, что у таски ещё можно переопределять методы такие как failed(). Правда, это не совсем красивый код выйдет. korshun2. Если правильно понял, то с результатами работы потока мы работаем с помощью setOnSucceeded,setOnFailed и т.д. Типа того. korshunА если потоков 5, 10, 50 и к каждому потребуется прописать хотя бы два вышеназванных события, то кода получится просто куча. Это как-то можно сократить ? 50 потоков или фоновых задачь? Не путайте. Обратите внимание на класс Service. Замечания в коментах. Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.05.2014, 12:24 |
|
||
|
Вопрос по javafx.concurrent
|
|||
|---|---|---|---|
|
#18+
Blazkowiczkorshun1. В Task-потоке делается запрос к mysql и если в запросе есть ошибка, то поток exception'ов не выкидывает и соответственно висит. "Висит" здесь очень не точный и не корректный термин для описания того что на самом деле происходит. Не прерывает своей работы, не смотря на ошибку - так можно выразиться ?:) BlazkowiczkorshunКонструкция Код: java 1. возвращает "java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-4", что логично и мало чего дает. Чет не понял. А зачем вы биндинг вызываете асинхронно в своих потоках? Биндить надо в начале инициализации. Ага, он и висит отдельно от потока. BlazkowiczkorshunЕсли запрос к БД поместить в Platform.runLater(() -> { }); то проблема решается, но тогда теряется сам смысл выноса запроса в поток, т.к. выполняется он будет в "основном" потоке, верно ? Нет, не верно. Не понятно как IllegalStateException связан с вашим кодом. У вас loginIn тоже в каком-то странном потоке выполняется? Или как? Обратите внимание, что у таски ещё можно переопределять методы такие как failed(). Правда, это не совсем красивый код выйдет. LoginIn - это отдельная функция, которая вызывается при клике на кнопку (биндинг в fxml сделан), которая, в свою очередь, создает поток, который лезет в БД, проверяет данные и т.п. В первым вопросом, в общем, разобрался сам. Вроде :) BlazkowiczkorshunА если потоков 5, 10, 50 и к каждому потребуется прописать хотя бы два вышеназванных события, то кода получится просто куча. Это как-то можно сократить ? 50 потоков или фоновых задачь? Не путайте. Обратите внимание на класс Service. Намек понял, забыл про этот класс! За комментарии особая благодарность! Если можно, еще один комментарий, по поводу Platform.runLater(() -> { }); Читая форумы и документацию мне казалось, что эта конструкция, если можно так выразиться, выносит то, что в ней прописано, из "дополнительного" в "основной" поток приложения. Но вы говорите, что это не так. Можно тогда пару слов о том, что это такое и в каких случаях используется ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.05.2014, 15:57 |
|
||
|
Вопрос по javafx.concurrent
|
|||
|---|---|---|---|
|
#18+
Еще один момент: Код: java 1. Можно поподробнее ? Такой способ в офф. доках присутствует, да и в принципе в форумных примерах ничего другого не встречал. Или вы клоните к тому, что нужно Service использовать ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.05.2014, 16:09 |
|
||
|
Вопрос по javafx.concurrent
|
|||
|---|---|---|---|
|
#18+
korshunНе прерывает своей работы, не смотря на ошибку - так можно выразиться ?:) В чем это проявляется-то? Исключение приводит к завершению потока. Если вы видите что он где-то "висит" и что-то "делает", то опишите в чем это проявляется. Если вы не поймали исключения это ещё не значит что поток "висит". korshunАга, он и висит отдельно от потока. LoginIn - это отдельная функция, которая вызывается при клике на кнопку (биндинг в fxml сделан), которая, в свою очередь, создает поток, который лезет в БД, проверяет данные и т.п. Тогда мне совершенно не понятен ваш код и его результат в виде IllegalStateException. korshunЕсли можно, еще один комментарий, по поводу Platform.runLater(() -> { }); Читая форумы и документацию мне казалось, что эта конструкция, если можно так выразиться, выносит то, что в ней прописано, из "дополнительного" в "основной" поток приложения. Но вы говорите, что это не так. Можно тогда пару слов о том, что это такое и в каких случаях используется ? Где я говорю, что это "не так"? GUI работает в одном единственном потоке. В нет происходит отрисовка, обработка событий и т.п. Все события помещаются в отдельную очередь и обрабатываются в этом потоке. Platform.runLater помещает содержимое Runnable в эту очередь. И со временем этот Runnable обрабатывается в GUI потоке после других событий помещенных в очередь до него. Я говорю что у вас первый вопрос не совпадает с кодом "под катом". Поэтому я не догоняю что вы сделали и зачем. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.05.2014, 16:10 |
|
||
|
Вопрос по javafx.concurrent
|
|||
|---|---|---|---|
|
#18+
BlazkowiczkorshunНе прерывает своей работы, не смотря на ошибку - так можно выразиться ?:) В чем это проявляется-то? Исключение приводит к завершению потока. Если вы видите что он где-то "висит" и что-то "делает", то опишите в чем это проявляется. Если вы не поймали исключения это ещё не значит что поток "висит". Запускаю проект в ide, и если ошибок нет, то закрытие "главного" Stage закрывает приложение (грубо говоря кнопка "стоп" становится неактивной и консоль говорит "Process finished with exit code 0"). Если же в запросе mysql сделать ошибку, то при закрытии Stage окно вроде бы закрывается, но кнопка "стоп" при этом остается активной и в консоли нет надписи о том, что процесс завершен. Ну и соответственно при принудительной остановке кнопкой "стоп" оно останавливается с сообщением "Process finished with exit code -1". Оттого и казалось, что поток как бы "висит" :) BlazkowiczkorshunАга, он и висит отдельно от потока. LoginIn - это отдельная функция, которая вызывается при клике на кнопку (биндинг в fxml сделан), которая, в свою очередь, создает поток, который лезет в БД, проверяет данные и т.п. Тогда мне совершенно не понятен ваш код и его результат в виде IllegalStateException. Под катом весь код класса. Если в нем сделать ошибку в запросе к БД (убрать кавычку к примеру), то вылазит java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-4 Если запрос выполнять в Platform.runLater(() -> { }); , то ошибка уже другая, более информативная: java.lang.NullPointerException at ru.korshun.coba.login.controllers.LoginController$LoginTask.call(LoginController.java:195) at ru.korshun.coba.login.controllers.LoginController$LoginTask.call(LoginController.java:171) Вот об этом речь, надеюсь теперь понятно объясняю :) public class LoginController implements Initializable { @FXML private Button loginButton; @FXML private Button cancelButton; @FXML private TextField loginField; @FXML private PasswordField passwordField; @FXML private Label errorLabel; @FXML private Pane loadPane; private LoginTask loginTask; private Sql sql; private ResultSet rs; private volatile boolean loginComplite = false; @Override public void initialize(URL location, ResourceBundle resources) { sql = new Sql(); /* * * БИНДИНГИ ЭЛЕМЕНТОВ ОКНА * */ /* * Клик в поле с логином */ loginField.setOnMouseClicked(event -> { loginField.requestFocus(); loginField.positionCaret(0); loginField.selectAll(); }); loginField.setOnKeyPressed(event -> { if(event.getCode().equals(KeyCode.ENTER)) { loginIn(loginField.getText(), passwordField.getText()); } }); /* * Клик в поле с паролем */ passwordField.setOnMouseClicked(event -> { passwordField.requestFocus(); passwordField.positionCaret(0); passwordField.selectAll(); }); passwordField.setOnKeyPressed(event -> { if(event.getCode().equals(KeyCode.ENTER)) { loginIn(loginField.getText(), passwordField.getText()); } }); /* * Кнопка "Логин" */ loginButton.setOnMouseClicked(mouseEvent -> loginIn(loginField.getText(),passwordField.getText())); /* * Закрытие окна */ cancelButton.setOnMouseClicked(mouseEvent -> StageController.closeStage("loginStage")); /* * ======================================================== * БИНДИНГИ КНОПОК ЛОГИНА И ЗАКРЫТИЯ ОКНА * <КОНЕЦ> */ } /* * ФУНКЦИЯ ПРОВЕРКИ ДАННЫХ ДЛЯ ВХОДА */ private void loginIn(String login,String password){ loadPane.setVisible(true); cancelButton.setDisable(true); loginField.setDisable(true); passwordField.setDisable(true); loginTask = new LoginTask(login,password); errorLabel.textProperty().bind(loginTask.messageProperty()); new Thread(loginTask).start(); /* * Действия при успешном выполнении потока */ loginTask.setOnSucceeded(event -> { if(loginTask.getValue() != null) { Var.userLevel = (int) loginTask.getValue().get("level"); Var.userFullName = (String) loginTask.getValue().get("fullName"); Var.userPacksFullName = (String) loginTask.getValue().get("packsFullName"); Var.userFilialID = (int) loginTask.getValue().get("filial"); Var.userType = (int) loginTask.getValue().get("type"); Var.userPOA = (String) loginTask.getValue().get("POA"); try { StageController .createStage("clientInfoStage", new Stage()) .setTitle("COBA") .showStage("clientInfo/fxml/ClientInfoFXML.fxml"); StageController.closeStage("loginStage"); } catch (Exception e) { Dialogs.create() .title("Ошибка") .message(null) .masthead(null) .showException(e); } } loadPane.setVisible(false); cancelButton.setDisable(false); loginField.setDisable(false); passwordField.setDisable(false); }); /* * Действия при ошибке в потоке */ loginTask.setOnFailed(event -> { loadPane.setVisible(false); cancelButton.setDisable(false); loginField.setDisable(false); passwordField.setDisable(false); Dialogs.create() .title("Ошибка") .message(null) .masthead(null) .showException(event.getSource().getException()); }); } /* * ФОНОВЫЙ КЛАСС ДЛЯ РАБОТЫ С БД И ПРОВЕРКОЙ ДАННЫХ ДЛЯ ВХОДА */ private class LoginTask extends Task<HashMap<String,Object>> { private String login,password; private HashMap<String,Object> userData = new HashMap<>(); public LoginTask(String _login,String _password) { this.login = _login; this.password = _password; updateMessage(""); } @Override protected HashMap<String,Object> call() throws Exception { if(login.length() > 0 & password.length() > 0) { rs = sql.queryToSql("SELECT * " + "FROM `users` " + "WHERE `login` = '" + login + "' " + "AND `pass` = '" + Function.md5(password) + Function.md5(Configuration.PASS_SALT) + "';"); if (rs.next()) { userData.put("level", rs.getInt("level")); userData.put("fullName", rs.getString("fullname")); userData.put("packsFullName", rs.getString("fullnamedog")); userData.put("filial", rs.getInt("idfilial")); userData.put("type", rs.getInt("type")); userData.put("POA", rs.getString("doveren")); return userData; } else { updateMessage("Введенные данные не верны"); return null; } } else { updateMessage("Введите логин и пароль"); return null; } } } } ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.05.2014, 16:33 |
|
||
|
Вопрос по javafx.concurrent
|
|||
|---|---|---|---|
|
#18+
Stacktrace для IllegalStateException покажите. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.05.2014, 16:35 |
|
||
|
Вопрос по javafx.concurrent
|
|||
|---|---|---|---|
|
#18+
Блин, сорри, в тэг "Java" забыл код поместить, дублирую тут: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153. 154. 155. 156. 157. 158. 159. 160. 161. 162. 163. 164. 165. 166. 167. 168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180. 181. 182. 183. 184. 185. 186. 187. 188. 189. 190. 191. 192. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.05.2014, 16:35 |
|
||
|
Вопрос по javafx.concurrent
|
|||
|---|---|---|---|
|
#18+
korshunЗапускаю проект в ide, и если ошибок нет, то закрытие "главного" Stage закрывает приложение (грубо говоря кнопка "стоп" становится неактивной и консоль говорит "Process finished with exit code 0"). Если же в запросе mysql сделать ошибку, то при закрытии Stage окно вроде бы закрывается, но кнопка "стоп" при этом остается активной и в консоли нет надписи о том, что процесс завершен. Ну и соответственно при принудительной остановке кнопкой "стоп" оно останавливается с сообщением "Process finished with exit code -1". Оттого и казалось, что поток как бы "висит" :) Вот это уже по существу. Нажмите "паузу" в IDE и посмотрите stack потока, который "висит". Потому что не очень понятно с чего бы ему висеть. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.05.2014, 16:37 |
|
||
|
Вопрос по javafx.concurrent
|
|||
|---|---|---|---|
|
#18+
BlazkowiczStacktrace для IllegalStateException покажите. Под спойлером смотрите, если правильно понял, о чем речь. Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.05.2014, 16:43 |
|
||
|
Вопрос по javafx.concurrent
|
|||
|---|---|---|---|
|
#18+
korshun at org.controlsfx.dialog.Dialogs.showException(Dialogs.java:496) at ru.korshun.coba.Sql.queryToSql(Sql.java:72) Ну, дык бага совсем в другом месте. В вашем классе Sql вы выполняете в фоновом потоке запрос. И оттуда же зачем-то дергаете Dialogs.showException, напрямую, что естественно нельзя делать из этого потока. Вместо этого стоило ловить failure, которые отработает в JavaFX потоке и уже оттуда показывать ошибку. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.05.2014, 16:49 |
|
||
|
Вопрос по javafx.concurrent
|
|||
|---|---|---|---|
|
#18+
BlazkowiczkorshunЗапускаю проект в ide, и если ошибок нет, то закрытие "главного" Stage закрывает приложение (грубо говоря кнопка "стоп" становится неактивной и консоль говорит "Process finished with exit code 0"). Если же в запросе mysql сделать ошибку, то при закрытии Stage окно вроде бы закрывается, но кнопка "стоп" при этом остается активной и в консоли нет надписи о том, что процесс завершен. Ну и соответственно при принудительной остановке кнопкой "стоп" оно останавливается с сообщением "Process finished with exit code -1". Оттого и казалось, что поток как бы "висит" :) Вот это уже по существу. Нажмите "паузу" в IDE и посмотрите stack потока, который "висит". Потому что не очень понятно с чего бы ему висеть. Stack такой же, как и в сообщении выше. Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.05.2014, 16:50 |
|
||
|
Вопрос по javafx.concurrent
|
|||
|---|---|---|---|
|
#18+
Blazkowiczkorshun at org.controlsfx.dialog.Dialogs.showException(Dialogs.java:496) at ru.korshun.coba.Sql.queryToSql(Sql.java:72) Ну, дык бага совсем в другом месте. В вашем классе Sql вы выполняете в фоновом потоке запрос. И оттуда же зачем-то дергаете Dialogs.showException, напрямую, что естественно нельзя делать из этого потока. Вместо этого стоило ловить failure, которые отработает в JavaFX потоке и уже оттуда показывать ошибку. Эх блин.. Спасибище одним словом!)) Получается в классе Sql из блока catch нужно убрать вызов Dialogs.showException, получается нужно просто оставить catch пустым, в этом нет ничего страшного ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.05.2014, 16:54 |
|
||
|
Вопрос по javafx.concurrent
|
|||
|---|---|---|---|
|
#18+
korshunПолучается в классе Sql из блока catch нужно убрать вызов Dialogs.showException, Да. korshunполучается нужно просто оставить catch пустым Нет. Либо заменить catch блок на throws объявление метода. Либо залогировать и выборосить через throw. Либо обернуть в RuntimeException чтобы нигде больше не париться с перепрокидыванием (не самый оптимальный вариант для новичка). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.05.2014, 20:12 |
|
||
|
Вопрос по javafx.concurrent
|
|||
|---|---|---|---|
|
#18+
Спасибо! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.05.2014, 07:01 |
|
||
|
Вопрос по javafx.concurrent
|
|||
|---|---|---|---|
|
#18+
Новую тему создавать не хочется, надеюсь можно задать пару вопросов в этой. Возник вопрос: а как вообще по-правильному определять, что все потоки (task'и или service'ы) завершились ? Самый простой пример: при открытии формы показываем пользователю либо анимированную картинку, либо выводим надпись "Ждите, загрузка..." и одновременно с этим запускаем несколько фоновых задач. По их окончанию надо надпись\картинку убрать, а как определять, что все задачи завершились ? В мой нубский ум приходит только одна мысль - это создание доп. класса, который бы принимал в конструктор кол-во запущенных потоков, а каждый из запущенных потоков при завершении увеличивал бы некую переменную на единицу. И соответственно когда эта переменная становилось бы равной количеству потоков, то выполнялись бы необходимые действия. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.06.2014, 14:43 |
|
||
|
|

start [/forum/topic.php?fid=59&msg=38640005&tid=2127093]: |
0ms |
get settings: |
6ms |
get forum list: |
16ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
149ms |
get topic data: |
12ms |
get forum data: |
3ms |
get page messages: |
77ms |
get tp. blocked users: |
2ms |
| others: | 252ms |
| total: | 523ms |

| 0 / 0 |
