private TaskResult ReadQueue(LazyQueue <TVal> queue)
        {
            var result = new TaskResult {
                Queue = queue
            };
            TVal current;

            if (_ignoreFailures)
            {
                try
                {
                    result.HasValue = queue.TryPeek(out current);
                }
                catch (Exception ex)
                {
                    LogWarning(ex);
                    current = default(TVal);
                }
            }
            else
            {
                result.HasValue = queue.TryPeek(out current);
            }
            result.Value = current;

            return(result);
        }
Пример #2
0
        private IEnumerable <T> GetAggregateEnumerable()
        {
            // Used to pick the right element from each sub query in the right order
            var comparer = new OrderingComparer <T>(Expression);

            // Create lazy queues over each sub query so we can lazily pull items from it
            var lazyQueues = _subQueries.Select(query => new LazyQueue <T>(query.GetEnumerator())).ToList();

            // Used to keep track of everything we've seen so far (we never show duplicates)
            var seen = new HashSet <T>(_equalityComparer);

            do
            {
                T             minElement = default(T);
                LazyQueue <T> minQueue   = null;

                // Run tasks in parallel
                var tasks = (from queue in lazyQueues
                             select Task.Factory.StartNew(() => {
                    T current;
                    return(new {
                        Empty = !queue.TryPeek(out current),
                        Value = current,
                        Queue = queue,
                    });
                })).ToArray();

                // Wait for everything to complete
                Task.WaitAll(tasks);

                foreach (var task in tasks)
                {
                    if (!task.Result.Empty)
                    {
                        // Keep track of the minimum element in the list
                        if (minElement == null || comparer.Compare(task.Result.Value, minElement) < 0)
                        {
                            minElement = task.Result.Value;
                            minQueue   = task.Result.Queue;
                        }
                    }
                    else
                    {
                        // Remove the enumerator if it's empty
                        lazyQueues.Remove(task.Result.Queue);
                    }
                }

                if (lazyQueues.Any())
                {
                    if (seen.Add(minElement))
                    {
                        yield return(minElement);
                    }

                    // Clear the top of the enumerator we just peeked
                    minQueue.Dequeue();
                }
            } while (lazyQueues.Any());
        }
        /// <summary>
        /// Reads the minimal set of queries
        /// </summary>
        /// <param name="comparer"></param>
        /// <returns></returns>
        private IEnumerable <TVal> ReadOrderedQueues(IComparer <TVal> comparer)
        {
            // Create lazy queues over each sub query so we can lazily pull items from it
            var lazyQueues = _subQueries.Select(query => new LazyQueue <TVal>(query.GetEnumerator())).ToList();

            // Used to keep track of everything we've seen so far (we never show duplicates)
            var seen = new HashSet <TVal>(_equalityComparer);

            do
            {
                TVal             minElement = default(TVal);
                LazyQueue <TVal> minQueue   = null;

                // Run tasks in parallel
                var tasks = (from queue in lazyQueues
                             select Task.Factory.StartNew <TaskResult>(() => ReadQueue(queue))
                             ).ToArray();

                // Wait for everything to complete
                Task.WaitAll(tasks);

                foreach (var task in tasks)
                {
                    if (task.Result.HasValue)
                    {
                        // Keep track of the minimum element in the list
                        if (minElement == null || comparer.Compare(task.Result.Value, minElement) < 0)
                        {
                            minElement = task.Result.Value;
                            minQueue   = task.Result.Queue;
                        }
                    }
                    else
                    {
                        // Remove the enumerator if it's empty
                        lazyQueues.Remove(task.Result.Queue);
                    }
                }

                if (lazyQueues.Any())
                {
                    if (seen.Add(minElement))
                    {
                        yield return(minElement);
                    }

                    // Clear the top of the enumerator we just peeked
                    minQueue.Dequeue();
                }
            } while (lazyQueues.Count > 0);
        }