TPL数据流适用于这种设计类型吗?

5

我目前正在研究如何模拟连接对象之间的资源和消息传输,例如将电源提供给设备或在网络系统上发送控制消息:

enter image description here 点击查看大图。

我最近一直在研究TPL Dataflow,不是因为它的线程和并行性能,而是因为它能够很好地实现数据管道,并且不需要处理大量混乱的代码来处理边缘情况。这个仿真只会每隔500ms左右运行一次,时间不是非常关键。

我一直在使用该库并阅读文档,但仍然无法找到解决方案。在上面所示的节点概念中,我不确定哪些适合Dataflow节点。

我希望能够得到一些建议,关于TPL Dataflow是否适用于此处,如果适用,还有每个图片节点对应的Dataflow Block基本实现方法。


那么大部分的蓝色箭头都是网络传输吗? - usr
你的模拟中时间有多重要?因为数据流节点大多是独立的,通常没有时间保证。此外,能源单位是离散的吗?换句话说,一个节点可以请求0.5个单位吗? - svick
@usr 所有蓝色箭头都是“连接”。 - S.Richmond
@svick 更新帖子:时间不重要,因为模拟只会每500毫秒左右才进行一次计时。一个节点可以请求其充电速率相等范围内的整数功率单位,其充电速率可以发生变化。 - S.Richmond
2个回答

5
我认为 TPL Dataflow 不是很适合。原因如下:
  1. TDF 没有双向通信,你需要想办法加上它。
  2. 在 TDF 中,块通常接收消息,然后产生更多消息以发送到管道中。这似乎不是你需要的(除了你的中心节点),至少在逻辑上不是。
但我认为你的要求并不需要像 TDF 那样重量级的东西。我认为你应该做的是:
  1. 创建一个简单的消息发送库,可能使用客户端-服务器架构:客户端(如消费者节点或分布节点)向服务器(如分布节点或功率节点)发送消息,并且服务器会回复,可能会有一些延迟。如果客户端连接到多个服务器,则将相同的消息发送到所有服务器,并决定如何处理多个响应(可能只接受第一个响应;这也意味着客户端必须能够拒绝响应)。
  2. 创建一个 PowerStore 类来存储电量并用于获取电量。它会返回一个 Task,因此消费者可以等待直到电量可用。
  3. 使用上述两点,构建你的节点应该相对简单。

2

经过深思熟虑、原型设计和研究,我最终使用事件和委托实现了解决方案,目前效果相当不错!

唯一的主要设计问题是,如果例如连接了3个分发节点成为三角形,或者一个节点连接到自身,或者2个节点多次连接,则会出现消息进入无限循环的情况。我通过事件监听器连接中的一些简单逻辑来处理这些边缘情况:

public bool ConnectTo(Node peerNode)
        {
            EthernetPort peerPort   = peerNode.GetFreePort();
            EthernetPort myPort     = this.GetFreePort();

            // Perform a check for free ports for both peers:
            if (peerPort == null || myPort == null)
                return false; // Either myself or my peer do not have a spare port.

            // Perform a check to make sure these nodes aren't already connected:
            if (this.HasConnectedNode(peerNode))
                return false;

            // Connect the two ports:
            myPort.Connect(peerNode, peerPort);
            peerPort.Connect(this, myPort);
            return true;
        }
public bool HasConnectedNode(Node node) {
            foreach (var port in ethernetSwitch.ethernetPorts)
            {
                if (port.peerNode == node)
                    return true; // Found a port already connected to this node.
            }

            return false; // No port has this node connected to it.
        }

最后,为了确保程序的正确性,我实现了一个自定义的EventArgs类型,并添加了一个int timeToLive变量。每次节点处理消息时,此变量将递减,如果它降为 0,则消息会被丢弃。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接