#multithreading #design-patterns
#многопоточность #дизайн-шаблоны
Вопрос:
Я работаю над имитационной моделью, которая повторяется по временным шагам. Иногда, когда результаты модели начинают ухудшаться, я хочу иметь возможность нажать на кнопку, чтобы остановить итерацию. Однако, если мое тестирование верно, когда итерация выполняется в потоке пользовательского интерфейса, кнопка.Событие щелчка не активируется, так как поток занят итерацией. Это правильно? Есть ли способ прервать поток пользовательского интерфейса нажатием кнопки, когда поток действительно занят?
Один из способов решения этой проблемы-создать задачу с использованием библиотеки параллельных задач для выполнения итераций, требующих больших вычислительных затрат. Я начинаю работать над этим подходом на случай, если нет возможности прервать поток пользовательского интерфейса, но я подумал, что проверю здесь, чтобы убедиться, что я не упускаю более простой подход.
Комментарии:
1. Никогда не должно быть ничего «запущенного в потоке пользовательского интерфейса». (См. Ответ Натана Хьюза ниже.) Поток пользовательского интерфейса должен реагировать только на события, которые могут включать события таймера , а также мышь, клавиатуру и другие события. Самый простой способ сделать что-то «повторяющимся по временным шагам» — это настроить периодический таймер, а затем продвигать состояние модели каждый раз, когда срабатывает таймер.
Ответ №1:
Проблема с вашей идеей прервать вычисления в потоке пользовательского интерфейса заключается в том, что для этого требуется сотрудничество потока пользовательского интерфейса, который уже заблокирован при выполнении ваших вычислений. Чтобы поток пользовательского интерфейса мог обработать ваше нажатие на кнопку, вычисление должно быть остановлено, чтобы поток мог вернуться к обработке событий пользовательского интерфейса. Это означает сохранение вашего прогресса, чтобы вы могли продолжить с того места, на котором остановились позже.
Такого рода приостановка и возобновление, скорее всего, вызовут больше проблем, чем включение вычисления в собственный поток, оно не может быть полностью отменено (браузер Netscape, разработанный JWZ, работал так в одном потоке), но причина, по которой поощряется многопоточный подход, заключается в том, что это способ, который требует наименьшей работы и сохраняет ваш код вычисления наиболее сфокусированным на домене и наименее измельченным.
Если вы поместите вычисления в свой собственный поток, то поток пользовательского интерфейса будет реагировать, ОС позаботится о том, чтобы оба потока были запущены. Вы можете периодически проверять расчеты на прерывание, у вас может быть индикатор выполнения с кнопкой «Отмена», и вам не придется беспокоиться о прекращении работы для обработки событий пользовательского интерфейса.
Я предполагаю пользовательский интерфейс, в котором у вас есть один поток отправки событий, который отвечает за обработку событий пользовательского интерфейса. Именно так работает Swing в Java, и это популярный выбор для множества наборов инструментов с графическим интерфейсом, потому что многопоточные решения подвержены блокировкам (события, исходящие от пользователя, будут блокироваться в другом порядке, чем события, исходящие с серверной части). Вы можете указать теги для языка и платформы, чтобы получить более релевантные ответы.