public Dataflow([NotNull] ITargetBlock <TInput> startingBlock, [NotNull] IDataflowBlock finalBlock) { if (startingBlock == null) { throw new ArgumentNullException(nameof(startingBlock)); } if (finalBlock == null) { throw new ArgumentNullException(nameof(finalBlock)); } if (finalBlock.GetType().GetInterfaces().Any(type => type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ISourceBlock <>))) { throw new ArgumentException(string.Format("Dataflow can not have final block of type {0} " + "because it can not be awaited after completition of it's input.", finalBlock.GetType()), nameof(finalBlock)); } this.startingBlock = startingBlock; this.finalBlock = finalBlock; this.status = DataflowStatus.NotStarted; }
/// <summary> /// Changes the dataflow <see cref="Status" /> to <see cref="DataflowStatus.InProgress" />. /// </summary> public void Start() { if (this.status != DataflowStatus.NotStarted) { throw new InvalidDataflowStatusException(this.status); } this.stopwatch = new Stopwatch(); this.stopwatch.Start(); this.status = DataflowStatus.InProgress; }
/// <summary> /// Signals the completion of data sending. /// Returns the task that will be completed when remaining data in dataflow is processed. /// </summary> public async Task CompleteAsync() { if (this.status != DataflowStatus.InProgress) { throw new InvalidDataflowStatusException(this.status); } this.startingBlock.Complete(); this.status = DataflowStatus.AllDataSent; var completion = this.startingBlock == this.finalBlock ? this.finalBlock.Completion : Task.WhenAll(this.startingBlock.Completion, this.finalBlock.Completion); await completion.ConfigureAwait(false); this.stopwatch.Stop(); this.status = DataflowStatus.Completed; }
public InvalidDataflowStatusException(DataflowStatus status, Exception innerException = null) : base(string.Format("Dataflow status is invalid {0} for performing current operation.", status), innerException) { this.status = status; }