예제 #1
0
        public Task <bool> MoveNext(CancellationToken cancel)
        {
            lock (factory)
            {
                if (producerTask != null && !producerTask.IsCompleted)
                {
                    return(TaskEx.Throw <bool>(new OverlappingMoveNextException()));
                }

                if (remaining <= 0)
                {
                    producerTask = null;
                    return(TaskConstants.False);
                }

                --remaining;
                producerTask = factory(context, cancel);
                if (producerTask.IsCompleted && !producerTask.IsFaulted && !producerTask.IsCanceled)
                {
                    return(TaskConstants.True);
                }

                return(WaitResultAsync());
            }
        }
예제 #2
0
        bool ProcessReadResults()
        {
            var cancel = cts.Token;

            lock (readers)
            {
                List <Exception> errors = null;

                int i = 0;
                while (i < activeReaderCount && !cancel.IsCancellationRequested)
                {
                    if (pendingReads[i] == null)
                    {
                        pendingReads[i] = readers[i].MoveNext(cancel);
                    }

                    var read = pendingReads[i];
                    if (!read.IsCompleted)                              // read result not yet available
                    {
                        ++i;
                    }
                    else if (read.IsFaulted)                            // source faulted
                    {
                        errors = read.Exception.InnerExceptions.ToList();
                        RemoveReader(i);
                        break;
                    }
                    else if (read.IsCanceled || !read.Result)           // source has no more data or read was canceled
                    {
                        RemoveReader(i);
                    }
                    else
                    {
                        available.Enqueue(readers[i].Current);

                        pendingReads[i] = readers[i].MoveNext(cancel);
                        ++i;
                    }
                }

                if (errors != null || cancel.IsCancellationRequested)
                {
                    Cancel();
                    available.Clear();
                    current         = default(T);
                    completedResult = errors != null?TaskEx.Throw <bool>(errors) : TaskConstants.CanceledTask <bool>();

                    return(false);
                }

                return(true);
            }
        }
예제 #3
0
 public static IWritable Create(Action <Stream> writeToFunc, IDisposable resource = null)
 {
     return(Create((stream, cancel) =>
     {
         try
         {
             writeToFunc(stream);
             return TaskConstants.Completed;
         }
         catch (Exception ex)
         {
             return TaskEx.Throw(ex);
         }
     }, resource));
 }
예제 #4
0
        public Task <bool> MoveNext(CancellationToken cancel)
        {
            if (stopped)
            {
                return(TaskEx.Throw <bool>(new ObjectDisposedException("AnonymousIterator", "The sequence iterator has been stopped.")));
            }

            try
            {
                return(next(cancel));
            }
            catch (Exception e)
            {
                Cancel();
                return(TaskEx.Throw <bool>(e));
            }
        }
예제 #5
0
        public Task <bool> MoveNext(CancellationToken cancel)
        {
            lock (selector)
            {
                if (moveNextTask != null && !moveNextTask.IsCompleted)
                {
                    return(TaskEx.Throw <bool>(new OverlappingMoveNextException()));
                }

                if (cts.IsCancellationRequested)
                {
                    return(TaskConstants.CanceledTask <bool>());
                }

                ClearCurrent();
                moveNextTask = source.MoveNext(cancel);
                if (!moveNextTask.IsCompleted)
                {
                    return(AwaitMoveNext());
                }

                if (moveNextTask.IsFaulted)
                {
                    Cancel();
                    return(moveNextTask);
                }

                if (moveNextTask.Result)
                {
                    try
                    {
                        current = selector(source.Current);
                        return(TaskConstants.True);
                    }
                    catch (Exception e)
                    {
                        return(TaskEx.Throw <bool>(e));
                    }
                }
                else
                {
                    return(TaskConstants.False);
                }
            }
        }
예제 #6
0
        public Task <bool> MoveNext(CancellationToken cancel)
        {
            if (completed)
            {
                return(TaskConstants.False);
            }

            try
            {
                // start all move next operations
                bool allCompletedSynchronously = true;
                for (int i = 0; i < iterators.Length; ++i)
                {
                    moveNextTasks[i] = iterators[i].MoveNext(cancel);           // exceptions during MoveNext() should be communicated through the task object
                    if (!moveNextTasks[i].IsCompleted)
                    {
                        allCompletedSynchronously = false;
                    }
                }

                if (!allCompletedSynchronously)
                {
                    // fall back to asynchronous await Task.WhenAll(moveNextTasks) ...
                    return(MoveNextInternalAsync(cancel));
                }

                for (int i = 0; i < iterators.Length; ++i)
                {
                    if (moveNextTasks[i].Result)
                    {
                        current[i] = iterators[i].Current;
                    }
                    else
                    {
                        // at least one iterator reached the end of its sequence, stop here
                        completed = true;
                        ClearCurrentAndStop();
                        return(TaskConstants.False);
                    }
                }
            }
            catch (AggregateException ae)
            {
                ClearCurrentAndStop();

                if (moveNextTasks.Any(x => x.IsFaulted))
                {
                    // one or more move next operation sgenerated an error
                    var errorList = moveNextTasks.Where(x => x.IsFaulted).SelectMany(x => x.Exception.InnerExceptions).ToArray();
                    return(TaskEx.Throw <bool>(errorList));
                }
                else if (ae.InnerException is OperationCanceledException || moveNextTasks.Any(x => x.IsCanceled))
                {
                    // one move next operation was canceled
                    return(TaskConstants.CanceledTask <bool>());
                }
                else
                {
                    return(TaskEx.Throw <bool>(ae));
                }
            }

            return(TaskConstants.True);
        }
예제 #7
0
        public Task <bool> MoveNext(CancellationToken cancel)
        {
            lock (gate)
            {
                if (completed)
                {
                    return(TaskConstants.False);
                }

                if (!AllMoveNextCallsCompleted())
                {
                    return(TaskEx.Throw <bool>(new OverlappingMoveNextException()));
                }

                current = default(T);

                if (cts.IsCancellationRequested || cancel.IsCancellationRequested)
                {
                    return(TaskConstants.CanceledTask <bool>());
                }

                try
                {
                    // start all move next operations
                    StartMoveNextOperations(cancel);

                    // check if all MoveNext() operations executed synchronously
                    if (!AllMoveNextCallsCompleted())
                    {
                        // fall back to asynchronous await Task.WhenAll(moveNextTasks) ...
                        return(MoveNextInternalAsync(cancel));
                    }

                    for (int i = 0; i < moveNextTasks.Length; ++i)
                    {
                        if (!moveNextTasks[i].Result)
                        {
                            // at least one iterator reached the end of its sequence, stop here
                            completed = true;
                            ClearCurrentAndStop();
                            return(TaskConstants.False);
                        }
                    }
                }
                catch (AggregateException ae)
                {
                    ClearCurrentAndStop();

                    if (moveNextTasks.Any(x => x.IsFaulted))
                    {
                        // one or more move next operation sgenerated an error
                        var errorList = moveNextTasks.Where(x => x.IsFaulted).SelectMany(x => x.Exception.InnerExceptions).ToArray();
                        return(TaskEx.Throw <bool>(errorList));
                    }
                    else if (ae.InnerException is OperationCanceledException || moveNextTasks.Any(x => x.IsCanceled))
                    {
                        // one move next operation was canceled
                        return(TaskConstants.CanceledTask <bool>());
                    }
                    else
                    {
                        return(TaskEx.Throw <bool>(ae));
                    }
                }

                try
                {
                    if (cts.IsCancellationRequested)
                    {
                        return(TaskConstants.CanceledTask <bool>());
                    }

                    current = Select();
                }
                catch (Exception error)
                {
                    return(TaskEx.Throw <bool>(error));
                }

                return(TaskConstants.True);
            }
        }
예제 #8
0
        protected override Task <bool> MoveNextInternal(CancellationToken cancel)
        {
            if (bindResult == null)      // double-checked locking
            {
                lock (gate)
                {
                    if (cts.IsCancellationRequested)
                    {
                        return(TaskEx.Throw <bool>(new Exception("Iterator was stopped")));
                    }

                    if (bindResult == null)
                    {
                        try
                        {
                            // try to bind sources synchronously
                            var bindTask = source.ToListAsync(cancel);
                            if (!bindTask.IsCompleted)
                            {
                                bindResult = ContinueBindAsync(bindTask, cancel);
                                return(bindResult);
                            }
                            else if (bindTask.IsFaulted)
                            {
                                return(TaskEx.Throw <bool>(bindTask.Exception.InnerExceptions));
                            }
                            else if (bindTask.IsCanceled)
                            {
                                return(TaskConstants.CanceledTask <bool>());
                            }

                            // we got the sequence list synchronously, now start the source sequences and pass our own context
                            var sourceSequences = bindTask.Result;
                            this.current       = new T[sourceSequences.Count];
                            this.moveNextTasks = new Task <bool> [sourceSequences.Count];

                            if (cancel.IsCancellationRequested)
                            {
                                return(TaskConstants.CanceledTask <bool>());
                            }

                            iterators       = sourceSequences.Select(x => x.Start(source.Context)).ToList();
                            this.bindResult = TaskConstants.True;
                        }
                        catch (Exception e)
                        {
                            return(TaskEx.Throw <bool>(e));
                        }
                    }
                }
            }

            if (!bindResult.IsCompleted)
            {
                return(TaskEx.Throw <bool>(new Exception("Previous MoveNext() has not been completed.")));
            }
            else if (bindResult.IsFaulted || bindResult.IsCanceled)
            {
                return(bindResult);
            }

            if (completed)
            {
                return(TaskConstants.False);
            }

            try
            {
                // start all move next operations
                bool allCompletedSynchronously = true;
                for (int i = 0; i < iterators.Count; ++i)
                {
                    moveNextTasks[i] = iterators[i].MoveNext(cancel);           // exceptions during MoveNext() should be communicated through the task object
                    if (!moveNextTasks[i].IsCompleted)
                    {
                        allCompletedSynchronously = false;
                    }
                }

                if (!allCompletedSynchronously)
                {
                    // fall back to asynchronous await Task.WhenAll(moveNextTasks) ...
                    return(MoveNextInternalAsync(cancel));
                }

                for (int i = 0; i < iterators.Count; ++i)
                {
                    if (moveNextTasks[i].Result)
                    {
                        current[i] = iterators[i].Current;
                    }
                    else
                    {
                        // at least one iterator reached the end of its sequence, stop here
                        completed = true;
                        ClearCurrent();
                        CancelInternal();
                        return(TaskConstants.False);
                    }
                }
            }
            catch (AggregateException ae)
            {
                ClearCurrent();

                if (moveNextTasks.Any(x => x.IsFaulted))
                {
                    // one or more move next operation sgenerated an error
                    var errorList = moveNextTasks.Where(x => x.IsFaulted).SelectMany(x => x.Exception.InnerExceptions).ToArray();
                    return(TaskEx.Throw <bool>(errorList));
                }
                else if (ae.InnerException is OperationCanceledException || moveNextTasks.Any(x => x.IsCanceled))
                {
                    // one move next operation was canceled
                    return(TaskConstants.CanceledTask <bool>());
                }
                else
                {
                    return(TaskEx.Throw <bool>(ae));
                }
            }

            return(TaskConstants.True);
        }