哪种代码模式最适合处理循环且可变的操作流
我的场景是一个应用程序在实时数据上循环工作并且期限很紧。
我在每个周期对数据采取一系列操作。我有在每个周期发生的操作(让我们用大写字母来称呼它们,例如 A、B、C..)和其他操作仅每 x 个周期发生一次(我们用小写字母来称呼它们,例如 d、e、f...)。一个流程模式示例,具有两个持久操作,其中一个发生周期为 3 个周期(周期结束用“|”标记):
A - B - d | A - B | A - B | A - B - d |...
此外,该模式可以在运行时根据用户的输入进行更改。因此可以在列表中添加或删除一些操作。例如,之前的模式删除了B,在A之后添加C,在C<之后添加e /strong> 周期为 2 个周期的情况会突然变为(更改周期以“->”标记):
...| A - B - d | -> A - d - C - e | A - C | A - C - e | A - d - C | A - C - e | A - C | A - d - C - e |...
现在我手动启动相互通信的线程WaitHandles 并且,如果操作量很大,请使用 Parallel.For。然后,当模式更改时,我可能必须终止某个线程,启动另一个线程,替换要等待的 WaitHandle...当模式更改时,我会出现死锁问题。我可以修复它们,但我想到最好有一个更灵活的解决方案,这样如果我以后需要更改模式,我已经拥有了所有工具来有效地完成它。
我对这个主题还很陌生,但我认为(也遵循向我建议的内容previoulsy)我需要一种调度程序。
我读过一些有关 Windows Workflow Foundation 的内容(我目前不知道它是否适合我的情况)和其他解决方案,但在花时间理解它之前我需要知道最好的方向。例如任务更适合这个?或者我应该坚持线程并创建一个 Scheduler 类来管理所有可能的情况(在这种情况下,我已经看到了有关模式更改的不同问题,如果您能更深入地研究该问题,我将不胜感激)?或者有更好的选择?
[编辑]
当循环中的前一个主要操作(A、B...)结束时,可以执行操作。次要操作(d、e...)可以同时执行。例如,在 A - B - d - e 动作 B 类型的循环中>只能在A之后执行,动作d只能在B之后执行,动作e只能在B之后执行也可能与d同时发生。 此外,如果我不将两个连续的主要操作分组(在示例中,人们可能会认为 A 和 B 由于它们的相互依赖性可以分组为一个单独的操作)在两个不同的线程中执行。原因是我使用循环缓冲区来存储中间结果(在示例中,结果来自 A,稍后将由 B 使用)。缓冲区可以帮助我在实时过程中不会丢失数据,以防由于某种原因过程中出现延迟(事实上,主要领导者操作 A 总是会以良好的计时精度发生,无论最后一个循环中的动作是否完成)。
My scenario is an application working cyclically on real time data and with tigh deadlines.
I have a serie of actions to take on data at each cycle. I've actions that take place at each cycle (let's call them with capital letters like A, B, C..) and other actions that take place only every x cycles (let's call them with lowercase letters like d, e, f,...). A flow pattern example, having two persistent actions and one taking place with a period of 3 cycle could be (end of cycle is marked by '|'):
A - B - d | A - B | A - B | A - B - d |...
Moreover, the pattern could change at runtime accordingly to users' input. So some actions could be added or removed from the list. For instance, the previous pattern by removing B, adding C after A and e after C with a period of 2 cycles would suddenly become (change cycle marked by '->'):
...| A - B - d | -> A - d - C - e | A - C | A - C - e | A - d - C | A - C - e | A - C | A - d - C - e |...
Right now I start manually threads that communicate each other through WaitHandles and that, in case the action is heavy, make use of Parallel.For. Then when the pattern changes I may have for instance to terminate a certain thread, launch another one, substitute the WaitHandle on which to wait on... I have deadlock problems that arise when the pattern changes. I could fix them, but I came to the idea that it would be much better to have a more flexible solution, so that if I need to change the pattern later on, I've already all the tools to do it efficiently.
I'm pretty new on this topic but I think (following also what it has been suggested to me previoulsy) I need a sort of scheduler.
I've read something about Windows Workflow Foundation (I do not know at the moment whether it's suitable for my situation) and other solutions but I would need to know the best direction to take before spending time on understanding it. For instance Tasks are more suitable for this? Or should I stick on threads and create a Scheduler class for managing all possible situations (In this case I see already different issues on the changing of patterns and I would be greatful if you could go deeper into the problem)? Or there are better alternatives?
[EDIT]
Actions can be executed when the previous main action (A, B,...) in the cycle has terminated. Minor actions (d, e,...) can be executed concurrently. For instance in a cylcle of type A - B - d - e action B can be executed only after A, action d only after B and action e only after B and also possibly concurrently with d.
Moreover, if I do not group two successive main actions (in the example one might think that A and B could be grouped into one single action because of their interdependency) it means that are executed in two different threads. The reason for this is that I use circular buffers for storing intermediate results (in the example the result coming from A and that will be later used by B). Buffers help me on not losing data during the real time process in case for some reason there is a delay in the process (in fact the main leader action A will always occur with a good timing accuracy regardless the last action in the cycle has finished or not).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我建议研究 Windows 工作流程并将委托绑定到状态机状态更改。
您可以跟踪周期计数 CycleIteration = Cycle++ % MaxCycleCount
并根据哪个迭代触发周期循环。
每个循环迭代都有一个工作流程,因此将其称为:
循环迭代 0:
A - B - d
循环迭代 1:
A - B
循环迭代 2:
A - B
循环迭代 3:
A - B - d
...
工作流状态机中的每个循环状态更改都基于迭代计数。您的每个单独的方法都会有一个委托,定义为包装在委托中以供重用的工作项。
每个循环迭代工作流程将由 FSM 保存和调用,如下所示:
CycleIteration1Execute(...){
调用A(...);
调用 B(...);
呼叫D(...);
返回;
然后
,循环顺序和循环状态的修改将被维护在易于维护的小逻辑块中。
编辑(提供 WF 实现示例):
WF 有限状态机示例:
这是一个非常适合初学者的示例,说明了如何进行 2 状态 FSM。
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
I would recommend looking into windows workflow and binding delegates to a state machine state changes.
You could track the cycle count CycleIteration = cycle++ % MaxCycleCount
And trigger the cycle loop based on which iteration.
You would have a work flow for each cycle iteration so call it:
Cycle Iteration 0:
A - B - d
Cycle Iteration 1:
A - B
Cycle Iteration 2:
A - B
Cycle Iteration 3:
A - B - d
...
Each cycle state change in the Workflow state machine is based on iteration count. Your each individual method would have a delegate defined as a work item wrapped in a delegate for re-use.
Each Cycle Iteration workflow would be saved and called by the FSM, and would look like:
CycleIteration1Execute(...){
callA(...);
callB(...);
callD(...);
return;
}
Then modification of cycle order and cycle states would be maintained in small logical easily maintained chunks.
Edit (Providing examples for WF implementation):
Example of WF Finite State Machine:
This is a VERY beginner example that illustrates how to do a 2 state FSM.
http://www.codeproject.com/KB/dotnet/FirstStateMachineWorkflow.aspx
Example provided by M$ (As with all their examples, very wordy but gives a bit more involved example):
http://msdn.microsoft.com/en-us/magazine/cc163281.aspx
And the best for last, a very well put together blog post on a State Machine using WF
http://odetocode.com/code/460.aspx