Последний раз редактировалось Владимир Ситников; 10.10.2017 в 19:03.
диалог опять превратился в то как вы "давите своим интеллектом", обсуждение нужности пауз превратилось в обсуждение что я выложил неправильный код. Напоминаю, что в выложенном Вами коде нет намека на дочитывание файла, не хотите принять что мой код проще Ваших замудренностей, да наздоровье
Bad programmers worry about the code. Good programmers worry about data structures and their relationships
среди успешных людей я не встречала нытиков
Барбара Коркоран
Если вы не увидили "дочитывание" в моём примере, что ж, жаль.
Полный пример был в 6-ом сообщении
И смысл 6-го сообщения в том, что REPEAT там как раз и используются для "дооткрывания", "дочитывания", "дозаписывания". Во 2-ом коде 6-го сообщения эти самые REPEAT фигурируют в коде явно. В последнем же коде 6-го сообщения эти "REPEAT" просто скрыты внутри вспомогательных функций OwenFileOpenAsync2.
Ну а в сообщении 14 я показал, что эти самые "REPEAT" не будут приводить к собакам, а раскроются компилятором в нехитрые CASE, и по факту за каждый ПЛК цикл будет очередное продвижение. Либо "дооткрывание", либо "дочитывание" и так далее.
Да, в моём примере наверняка неправильно рассматриваются коды возвратов, но именно на механизм "дочитывания" они не влияют.
У вас код работает *только* для случая, когда всё чтение сработает успешно и за 1 цикл ПЛК.
Разумеется, для такого конкретного случая ваш код проще (вернее, он визуально ничем от моего не отличается, но не суть). Да и вообще сложно придумать что-то проще 3х последовательных вызовов функции.
Но, вместе с этим, я не согласен, что случай "дочитывания" останется "таким же кристально ясным". Поэтому и прошу: покажите как реально выглядел бы код с дочитыванием -- тогда можно будет сравнить "обычный и понятный ST код" с предлагаемым мной подходом.
Сейчас получается интересно: я показываю своё сравнение (как обычный ST так и ST-с-паузами, "обычный код" длиннее в 6 раз, а поведение при этом абсолютно идентично), вы говорите "да это всё ненужно, обычный проще", но при этом показываете код, решающий гораздо более простую задачу.
Последний раз редактировалось Владимир Ситников; 10.10.2017 в 19:23.
Снова мимо кассы?
"события", "state machine" это, да, может требоваться одновременно с асинхронным выполнением, но это не исключающие, а дополняющие друг друга штуки.
Пример:
"работа с файлом" -- это просто асинхронный код (возможно, с небольшим ветвлением, но почти прямолинейно)
На примере с файлом видно, что "никакие события" там не нужны. Просто берём и используем.
"обработка сетевого протокола" -- тут, возможно, поинтереснее. И, вполне возможно, что тут нужна комбинация автомата (ну, обычного) и асинхронщины.
Как вариант, можно сделать "полноценную библиотеку modbus" и посмотреть потребуются ли там "события" или нет.
Тут я вас поправлю: пост 35 называется "а в императивном духе гораздо проще".
К потокам он не имеет отношения, т.к. я с самого начала заявлял, что код не будет "блокироваться".
Потоки обычно используют тогда, когда нужно выполнить блокирующийся код, и так, чтобы основной поток не страдал из-за этих блокировок.
Я же говорю про async/await/coroutines/fibers -- когда "сама работа делится на небольшие кусочки и выполняется понемногу".
Смысл не в том, чтобы "с помощью какой-то матери создать поток в КДС", а в том, чтобы "составлять программу в обычном императивном стиле, а компилятор при этом подменял код на автомат, прерывающийся и продолжающий работать оттуда, где закончил".
Да, грубо (ну, очень грубо) можно это назвать потоками, но это называется fiber, coroutine и т.п.
1) Разумеется, "просто 1 раз вызвать автомат недостаточно". Нужно сначала его сбросить, потом вызывать (пока он не закончится). Поэтому, да, у "сгенерированного автомата" должен быть какой-то признак, что он "закончился".
2) Но тут стоит понимать, что и сам автомат и вызывающий код генерирует один и тот же компилятор. Он-то может сам с собой договориться, как он будет определять, что "вызываемый автомат закончился"? Например, использовать state=-1 как признак "самого финального" состояния. Или просто var_output done:bool. Мало ли способов?
А, если автомат вызывается "из обычного кода", то он ничем не отличается от других "асинхронных" ФБ, у которых признак "done:bool" появляется за несколько циклов.
Ну и ещё: "послать событие" можно через установку input переменной. Например, "cancel=TRUE". И потом ждать, пока он "закончится".
И "асинхронный ФБ" будет проверять в нужных местах этот cancel флаг и делать что нужно. Например, если успел открыть файл, то переходить к закрытию и т.п.
Вполне норм, нет?
Ну, да, где обычный код будет уходить в собаку асинхронный будет "зависать на шаге".
По-моему, второе гораздо лучше, т.к. вручную вызвать собаку всегда можно, а вот понять "а где же код зациклился" после собаки уже никак.
Ась? Как раз coroutine это и есть одно слово и ровно обозначающее то, о чём я говорю.
Семечки уж точно мимо кассы.Сопрограмма (англ. coroutine) — компонент программы, обобщающий понятие подпрограммы, который дополнительно поддерживает множество входных точек (а не одну, как подпрограмма), остановку и продолжение выполнения с сохранением определённого положения.
Вопрос хороший, но тут же мозги нужны.
coroutine легко подсмотреть (и ничего кроме спинного мозга для этого не нужно), например, у Kotlin: https://kotlinlang.org/docs/reference/coroutines.html
И тут же оказывается, что в Kotlin'е не предлагается никаких "автоматизированных" механизмов для отправки событий-флажков.
Технически, если перед каждым "пинком" вложенного автомата ему заново переприсваивать INPUT переменные, то как раз флажки сами собой и будут пробрасываться.
Но нужно смотреть зачем вообще эти флажки могут быть нужны.Код:FB modbus_mddv_16r(..., cancel: bool) ... выполнить_полностью lib_modbus_send(cancel := cancel); (* этот самый cancel может пробасываться *)