/// <summary> /// ContinueWith specified <see cref="Action{T}" /> on each <see cref="Task" /> on the GraphSet /// </summary> /// <typeparam name="T">Type of the elements</typeparam> /// <param name="set">The set.</param> /// <param name="action">The action.</param> /// <returns><see cref="GraphSet{TaskPair}" /> with continuation tasks.</returns> /// <exception cref="System.InvalidOperationException">Cannot process task on a cyclic graph</exception> public static GraphSet <TaskPair <T> > ContinueWith <T>(this GraphSet <TaskPair <T> > set, Action <T> action) { if (set.IsCyclic()) { throw new InvalidOperationException("Cannot process task on a cyclic graph"); } var tasks = new Dictionary <GraphNode <TaskPair <T> >, Task>(); var taskSet = set.ToGraphSet(x => new TaskPair <T>(x.Value) { Task = x.Task }); foreach (var node in taskSet.GetNodes()) { tasks[node] = node.Value.Task; node.Value.Task = null; } var nodes = taskSet.GetNodes().Where(n => n.Parents.Count == 0).ToArray(); foreach (var node in nodes) { node.Value.Task = tasks[node].ContinueWith(t => action(node.Value.Value)); } var queue = new Queue <GraphNode <TaskPair <T> > >(nodes); while (queue.Any()) { var node = queue.Dequeue(); if (node.Value.Task == null) { var allParentsHaveTask = node.Parents.All(x => x.Value.Task != null); if (allParentsHaveTask) { var list = node.Parents.Select(x => x.Value.Task).ToList(); list.Add(tasks[node]); node.Value.Task = Task.Factory.ContinueWhenAll( list.ToArray(), x => action(node.Value.Value)); } queue.Enqueue(node); } else { foreach (var child in node.Children) { if (child.Value.Task == null) { queue.Enqueue(child); } } } } return(taskSet); }
/// <summary> /// ContinueWith specified <see cref="Action{T}" /> on the leaves of the GraphSet. /// </summary> /// <typeparam name="T">Type of the elements</typeparam> /// <param name="set">The set.</param> /// <param name="action">The action.</param> /// <returns><see cref="GraphSet{TaskPair}" /> with continuation tasks.</returns> /// <exception cref="System.InvalidOperationException">Cannot process task on a cyclic graph</exception> public static GraphSet <TaskPair <T> > ContinueOnLeavesWith <T>(this GraphSet <TaskPair <T> > set, Action <T> action) { if (set.IsCyclic()) { throw new InvalidOperationException("Cannot process task on a cyclic graph"); } var taskSet = set.ToGraphSet(x => new TaskPair <T>(x.Value) { Task = x.Task }); var graphNodes = taskSet.GetNodes().Where(x => x.Children.Count == 0); foreach (var node in graphNodes) { node.Value.Task = node.Value.Task.ContinueWith(x => action(node.Value.Value)); } return(taskSet); }
/// <summary> /// Transforms a <see cref="GraphSet{T}" /> to a GraphSet of Task executing the <see cref="Action{T}" /> on /// each of the nodes while respecting the graph order. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="set">The set.</param> /// <param name="action">The action.</param> /// <returns> /// <see cref="GraphSet{TaskPair}" /> /// </returns> /// <exception cref="System.InvalidOperationException">Cannot process task on a cyclic graph</exception> public static GraphSet <TaskPair <T> > ToTaskGraph <T>(this GraphSet <T> set, Action <T> action) { if (set.IsCyclic()) { throw new InvalidOperationException("Cannot process task on a cyclic graph"); } var taskSet = set.ToGraphSet(x => new TaskPair <T>(x)); var nodes = taskSet.GetNodes().Where(n => n.Parents.Count == 0).ToArray(); foreach (var node in nodes) { node.Value.Task = Task.Factory.StartNew(() => { action(node.Value.Value); }); } var queue = new Queue <GraphNode <TaskPair <T> > >(nodes); while (queue.Any()) { var node = queue.Dequeue(); if (node.Value.Task == null) { var allParentsHaveTask = node.Parents.All(x => x.Value.Task != null); if (allParentsHaveTask) { node.Value.Task = Task.Factory.ContinueWhenAll( node.Parents.Select(x => x.Value.Task).ToArray(), x => { action(node.Value.Value); }); } queue.Enqueue(node); } else { foreach (var child in node.Children) { if (child.Value.Task == null) { queue.Enqueue(child); } } } } return(taskSet); }