private static async Task <bool> CopyToQueue <T>(this IIterator <T> source, AsyncQueue <T> destination, int count, CancellationToken cancel, bool complete = false) { try { for (; count > 0; --count) { if (!await source.MoveNext(cancel).ConfigureAwait(false)) { if (complete) { destination.OnCompleted(); } return(false); } await destination.OnNext(source.Current, cancel).ConfigureAwait(false); } if (complete) { destination.OnCompleted(); } } catch (Exception e) { destination.OnError(e); throw; } return(true); }
async Task BindToSources(IIterator <ISequence <T> > source, CancellationToken cancel) { try { while (await source.MoveNext(cancel).ConfigureAwait(false)) { await Enter(cancel).ConfigureAwait(false); Tuple <IIterator <T>, Task> entry; var iterator = source.Current.Start(source.Context); var readTask = Read(iterator, cancel); lock (readers) { entry = Tuple.Create(iterator, readTask); this.readers.Add(entry); } var t = readTask.Finally(() => { lock (readers) { StopReader(entry.Item1); readers.Remove(entry); } Leave(); }); } await Task.WhenAll(this.ReaderTasks); queue.OnCompleted(); } catch (Exception e) { queue.OnError(e); // pass exception on to outer iterator throw; } }
public static ISequence <T> CreateProducer <T>(Func <IAsyncObserver <T>, CancellationToken, Task> producer, int queueLimit) { return(Create(context => { var cts = new CancellationTokenSource(); var queue = new AsyncQueue <T>(queueLimit); var task = producer(queue, cts.Token) .ContinueWith(t => queue.OnError(t.Exception), TaskContinuationOptions.OnlyOnFaulted); return Iterator.Create( moveNext: queue.MoveNext, current: () => queue.Current, cancel: cts.Cancel, stop: () => EnumerableEx.Return(task), context: context ); })); }
public ShareSource(IIterator <T> sourceIterator, int maxQueueLength) { this.SourceIterator = sourceIterator; this.Queue = new AsyncQueue <T>(maxQueueLength); this.readTask = Read(); readTask.ContinueWith(t => { if (t.IsFaulted) { Queue.OnError(t.Exception); } else if (t.IsCompleted) { Queue.OnCompleted(); } else if (t.IsCanceled) { Queue.Dispose(); } }); }