Какой шаблон кода лучше всего подходит для обработки циклического и изменчивого потока действий

Мой сценарий представляет собой приложение, циклически работающее с данными в реальном времени и с жесткими сроками.

У меня есть ряд действий для обработки данных в каждом цикле. У меня есть действия, которые происходят в каждом цикле (назовем их заглавными буквами, например A, B, C..) и другие действия которые происходят только каждые x циклов (назовем их строчными буквами, такими как d, e, f,...). Примером шаблона потока, имеющего два постоянных действия и одно, происходящее с периодом в 3 цикла, может быть (конец цикла отмечен знаком «|»):

A - B - d | А - Б | А - Б | A - B - d |...

Более того, шаблон может меняться во время выполнения в зависимости от действий пользователей. Таким образом, некоторые действия могут быть добавлены или удалены из списка. Например, предыдущий шаблон с удалением B, добавлением C после A и e после C< /strong> с периодом в 2 цикла вдруг станет (цикл изменения помечен '->'):

...| A - B - d | -> A - d - C - e | А - В | A - C - e | A - d - C | A - C - e | А - В | A - d - C - e |...

Прямо сейчас я запускаю вручную потоки, которые взаимодействуют друг с другом через WaitHandles и которые, если действие тяжелое, используют Parallel.For. Затем, когда шаблон изменится, мне, возможно, придется, например, завершить определенный поток, запустить другой, заменить WaitHandle, на котором нужно ждать... У меня возникают проблемы с взаимоблокировкой, которые возникают при изменении шаблона. Я мог бы их исправить, но пришел к мысли, что было бы гораздо лучше иметь более гибкое решение, чтобы, если мне нужно будет изменить шаблон позже, у меня уже были все инструменты, чтобы сделать это эффективно.

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

Я кое-что читал о Windows Workflow Foundation (на данный момент я не знаю, подходит ли он для моей ситуации) и других решениях, но мне нужно знать, в каком направлении лучше двигаться, прежде чем тратить время на его понимание. Например Задачи больше подходят для этого? Или я должен придерживаться потоков и создать класс планировщика для управления всеми возможными ситуациями (в этом случае я вижу уже разные проблемы с изменением шаблонов, и я был бы признателен, если бы вы могли углубиться в проблему)? Или есть лучшие альтернативы?

[EDIT]
Действия могут быть выполнены, когда предыдущее основное действие (A, B,...) в цикле завершилось. Незначительные действия (d, e,...) могут выполняться одновременно. Например, в цикле типа A - B - d - e действие B может быть выполнено только после A, действие d только после B и действие e только после B , а также, возможно, одновременно с d. Более того, если я не группирую два последовательных основных действия (в примере можно подумать, что A и B можно сгруппировать в одно действие из-за их взаимозависимости), это означает которые выполняются в двух разных потоках. Причина этого в том, что я использую циклические буферы для хранения промежуточных результатов (в примере результат поступает от A и позже будет использоваться B). Буферы помогают мне не терять данные во время процесса в реальном времени, если по какой-то причине происходит задержка в процессе (на самом деле основное действие лидера A всегда будет происходить с хорошей точностью по времени, независимо от последнего действие в цикле завершилось или нет).


person Mauro Ganswer    schedule 25.02.2011    source источник
comment
Мне непонятно, для чего вы используете потоки и зачем вам синхронизация. При обработке цикла ABd все ли они обрабатываются одновременно или существуют зависимости (например, d не может быть обработан, пока AB не будет выполнено? Можете ли вы немного расширить это?   -  person Jim Mischel    schedule 25.02.2011
comment
Вы правы, это было не так однозначно. Я надеюсь, что разъяснил это в разделе редактирования   -  person Mauro Ganswer    schedule 26.02.2011
comment
А в A-d-C-e должен ли C ждать завершения d?   -  person Jim Mischel    schedule 26.02.2011
comment
Нет, действия зависят только от предыдущих основных действий, поэтому C будет зависеть от завершения A.   -  person Mauro Ganswer    schedule 26.02.2011


Ответы (1)


Я бы рекомендовал изучить рабочий процесс Windows и привязать делегатов к изменениям состояния конечного автомата.

Вы можете отслеживать количество циклов CycleIteration = cycle++ % MaxCycleCount

И запускать цикл цикла, в зависимости от того, какая итерация.

У вас будет рабочий поток для каждой итерации цикла, поэтому назовите его:

Итерация цикла 0: A - B - d

Итерация цикла 1: A - B

Итерация цикла 2: A - B

Итерация цикла 3: A - B - d

...

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

Каждый рабочий процесс циклической итерации будет сохранен и вызван FSM и будет выглядеть так:

CycleIteration1Execute(...){ callA(...); вызовБ(...); вызовД(...); возвращение; }

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

Изменить (с примерами реализации WF):

Пример конечного автомата WF. Это пример для ОЧЕНЬ начинающих, который иллюстрирует, как сделать автомат с двумя состояниями.

http://www.codeproject.com/KB/dotnet/FirstStateMachineWorkflow.aspx

Пример предоставлен M$ (как и все их примеры, очень многословный, но дает немного более сложный пример):

http://msdn.microsoft.com/en-us/magazine/cc163281.aspx

И самое лучшее напоследок: хорошо составленный пост в блоге о конечной машине с использованием WF

http://odetocode.com/code/460.aspx

person VulgarBinary    schedule 25.02.2011
comment
Вы можете обрабатывать многопоточность таким же образом, просто это будет в переключателе оценки состояния. Каждый рабочий процесс Cycle Iteration может быть отдельным потоком, и каждый из них может запускать дополнительный поток для каждого процесса. Если вам нужно подключиться к глобальному случаю (которым может быть метод StateEvaluation), вы можете связать обработчик событий, к которому потоки FSM могут обращаться, чтобы обновить свой статус, к элементу управления верхнего уровня. - person VulgarBinary; 25.02.2011
comment
Как я уже сказал, я новичок в этой теме. Ваше предложение кажется чем-то интересным (и я надеюсь получить другое подтверждение этому, чтобы быть уверенным, что выбрал правильное направление), но мне нужно лучше понять его. Не могли бы вы порекомендовать мне какой-нибудь онлайн-учебник по WF и по его интеграции с моим существующим кодом? - person Mauro Ganswer; 25.02.2011
comment
WF предоставляет несколько довольно мощных хуков для управления конечным автоматом и приятный / многоразовый интерфейс для работы с ними. Вы можете сделать то же самое, написав свой собственный конечный автомат (поскольку WF немного тяжеловат для простых случаев), если вы держите в уме то, что на самом деле представляет собой FSM. Тем не менее, WF справится с вашим конечным автоматом и предоставит вам хорошую диаграмму для управления им. На самом деле, независимо от того, используете ли вы WF для решения своей проблемы, правильный подход заключается в написании или использовании конечного автомата для управления вашим потоком. - person VulgarBinary; 25.02.2011
comment
Если сегодня вечером у меня будет свободное время, я напишу для вас пример кода, как обрабатывать состояния, или хотя бы примерный случай. Есть хороший пример проекта, который вы можете скачать на домашней странице WF, но последнее сообщение в блоге, которое я разместил в ответе выше, действительно шаг за шагом проведет вас через то, чего вы хотите достичь. - person VulgarBinary; 25.02.2011
comment
большое спасибо, я начну с просмотра ссылок, которые вы предоставили - person Mauro Ganswer; 26.02.2011