Search code examples
c#.nettask-parallel-librarydataflow

Will TPL Dataflow work for this design type?


I'm currently looking into ways to simulate the transmission of resources and messages between connected objects such as power to devices or control messages over a networked system:

enter image description here CLICK FOR LARGER IMAGE.

I've been recently looking into TPL Dataflow not for its threading and parallelism but for how well it can implement pipelining of data without large messy code handling edge cases. The simulation will only run maybe once every 500ms or so and is really not time critical.

I've been playing around with the library and have read the documentation and few times now but I'm struggling to realize a solution with it. Of the node concepts above pictured I'm not sure what would fit the Dataflow nodes.

I would love to get some advise around whether TPL Dataflow is a good fit here, and if so a basic implementation of each of the pictured nodes in the Dataflow Block counterparts.


Solution

  • After much thought, prototyping and research I've finally implemented the solution using Events and Delegates and its working quite well!

    The only major design problem is that there will be cases where messages will enter an infinite loop if, for example, 3 distribution nodes were connected in a triangle. Or if a node is connected to itself or 2 nodes connected to each other more than once. I covered each of these edge cases with some simple logic in the event listener connections:

    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.
            }
    

    Finally, just in case I missed something or to simply feel safe about it, I implemented a custom EventArgs type with a int timeToLive variable. This variable is decremented each time a node handles the message and if it hits 0 then the message is discarded.