public static Task Execute(CancellationToken token, int bufferSize, IDataAdapter <TP, TC> adapter, IReadOnlyList <IProducer <TP> > producers, IReadOnlyList <IConsumer <TC> > consumers) { return(Task.Run(async() => { using (var localCts = new CancellationTokenSource()) { using (var combinedCts = CancellationTokenSource .CreateLinkedTokenSource(token, localCts.Token)) { using (var ppcBuffer = new PpcBuffer <TP>(bufferSize, combinedCts.Token)) { try { var rc = RunConsumers(consumers, ppcBuffer, adapter, combinedCts.Token, localCts); var rp = RunProducers(producers, ppcBuffer, combinedCts.Token, localCts); await Task.WhenAll(rc, rp).ConfigureAwait(false); } catch (Exception e) { if (token.IsCancellationRequested) { throw new OperationCanceledException("PpcCancelled", e, token); } throw; } } } } }, CancellationToken.None)); }
public Pipeline(IReadOnlyList <IConsumer <TC> > consumers, IDataAdapter <TP, TC> adapter, CancellationToken token, int bufferSize) { _localCts = new CancellationTokenSource(); _mergedCts = CancellationTokenSource.CreateLinkedTokenSource(token, _localCts.Token); //we pass "_mergedCts.Token" so that it starts throwing error when either consumer is in error //or tear-down is called or the Ctor token is cancelled. _feed = new PpcBuffer <TP>(bufferSize, _mergedCts.Token); //we give original token to consumers to listen to... so we can cancel "_localCts" in dispose //and still let consumer run to finish remaining objects. //However, if something goes wrong with consumers, we need to cancel "_localCts" //so that Add/TryAdd method also start throwing error _consumerTask = Pipe <TP, TC> .RunConsumers(consumers, _feed, adapter, token, _localCts); }
private static Task RunProducers(IReadOnlyList <IProducer <TP> > producers, PpcBuffer <TP> buffer, CancellationToken token, CancellationTokenSource tokenSrc) { return(Task.Run(async() => { try { await new Func <int, CancellationToken, Task>(async(i, t) => await RunProducer(producers[i], buffer, t, tokenSrc).ConfigureAwait(false)) .WhenAll(producers.Count, token).ConfigureAwait(false); } finally { buffer.Close(); } }, CancellationToken.None)); }