protected internal override void OnQueryErrorChanged( VirtualPage page, AsyncQueryInfo queryInfo )
    {
      base.OnQueryErrorChanged( page, queryInfo );

      // It is possible that m_asyncQueryInfosInProgress does not contain the queryInfo when
      // the query was aborted but the user did not stop the query and later on set the queryInfo error
      // event if the queryInfo ShouldAbort is set to True.
      Debug.Assert( ( m_asyncQueryInfosInProgress.Contains( queryInfo ) ) || ( queryInfo.ShouldAbort ) );

      object error = queryInfo.Error;

      if( error == null )
      {
        // Even if the queryInfo's ShouldAbort property is set to True, clean-up the error.
        Debug.Assert( ( m_asyncQueryInfosInError != null ) && ( m_asyncQueryInfosInError.Contains( queryInfo ) ) );

        m_asyncQueryInfosInError.Remove( queryInfo );

        if( m_asyncQueryInfosInError.Count == 0 )
          m_asyncQueryInfosInError = null;
      }
      else if( !queryInfo.ShouldAbort )
      {
        // Only add errors if the queryInfo's ShouldAbort property is set to False.
        if( m_asyncQueryInfosInError == null )
          m_asyncQueryInfosInError = new LinkedList<AsyncQueryInfo>();

        if( m_asyncQueryInfosInError.Contains( queryInfo ) )
          m_asyncQueryInfosInError.Remove( queryInfo );

        m_asyncQueryInfosInError.AddFirst( queryInfo );
      }

      this.UpdateConnectionState();
    }
        protected internal override void OnQueryItems(VirtualPage page, AsyncQueryInfo queryInfo)
        {
            base.OnQueryItems(page, queryInfo);

            DataGridVirtualizingQueryableCollectionViewGroup collectionViewGroup =
                this.GetLinkedCollectionViewGroup(page.ParentVirtualList) as DataGridVirtualizingQueryableCollectionViewGroup;

            IQueryable queryableToUse;

            int virtualItemCount = collectionViewGroup.VirtualItemCount;

            bool queryableIsReversed;

            if ((!m_supportsPrimaryKeyOptimizations) || (queryInfo.StartIndex < (virtualItemCount / 2)))
            {
                queryableIsReversed = false;
                queryableToUse      = collectionViewGroup.Queryable.Slice(queryInfo.StartIndex, queryInfo.RequestedItemCount);
            }
            else
            {
                queryableIsReversed = true;

                int reversedStartIndex = virtualItemCount - (queryInfo.StartIndex + queryInfo.RequestedItemCount);

                queryableToUse = collectionViewGroup.ReversedQueryable.Slice(reversedStartIndex, queryInfo.RequestedItemCount);
            }

            System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(this.AsyncGatherItems), new object[] { queryInfo, queryableToUse, queryableIsReversed });
        }
    protected internal override void OnQueryItems( VirtualPage page, AsyncQueryInfo queryInfo )
    {
      // The VirtualPageManager is not connected to the CollectionView anymore,
      // do NOT query items since it will be done by the new VirtualPageManager
      // assigned to the same CollectionView
      if( !this.IsConnected )
        return;

      Debug.Assert( !m_asyncQueryInfosInProgress.Contains( queryInfo ) );
      m_asyncQueryInfosInProgress.Add( queryInfo );

      if( m_asyncQueryInfosInError != null )
      {
        LinkedListNode<AsyncQueryInfo> queryInfoInErrorNode = m_asyncQueryInfosInError.First;

        while( queryInfoInErrorNode != null )
        {
          if( DataGridPageManagerBase.QueryInfoWeakComparer.Equals( queryInfo, queryInfoInErrorNode.Value ) )
          {
            m_asyncQueryInfosInError.Remove( queryInfoInErrorNode );
            break;
          }

          queryInfoInErrorNode = queryInfoInErrorNode.Next;
        }

        if( m_asyncQueryInfosInError.Count == 0 )
          m_asyncQueryInfosInError = null;
      }

      this.UpdateConnectionState();
    }
    protected internal override void OnQueryItems( VirtualPage page, AsyncQueryInfo queryInfo )
    {
      base.OnQueryItems( page, queryInfo );

      DataGridVirtualizingQueryableCollectionViewGroup collectionViewGroup =
        this.GetLinkedCollectionViewGroup( page.ParentVirtualList ) as DataGridVirtualizingQueryableCollectionViewGroup;

      IQueryable queryableToUse;

      int virtualItemCount = collectionViewGroup.VirtualItemCount;

      bool queryableIsReversed;

      if( ( !m_supportsPrimaryKeyOptimizations ) || ( queryInfo.StartIndex < ( virtualItemCount / 2 ) ) )
      {
        queryableIsReversed = false;
        queryableToUse = collectionViewGroup.Queryable.Slice( queryInfo.StartIndex, queryInfo.RequestedItemCount );
      }
      else
      {
        queryableIsReversed = true;

        int reversedStartIndex = virtualItemCount - ( queryInfo.StartIndex + queryInfo.RequestedItemCount );

        queryableToUse = collectionViewGroup.ReversedQueryable.Slice( reversedStartIndex, queryInfo.RequestedItemCount );
      }

      System.Threading.ThreadPool.QueueUserWorkItem( new System.Threading.WaitCallback( this.AsyncGatherItems ), new object[] { queryInfo, queryableToUse, queryableIsReversed } );
    }
Beispiel #5
0
        private void AsyncQueryInfo_QueryErrorChanged(AsyncQueryInfo queryInfo)
        {
            this.ParentVirtualList.PagingManager.OnQueryErrorChanged(this, queryInfo);

            if (this.ParentVirtualList.IsRestarting)
            {
                this.Restart();
            }
        }
        protected internal override void OnQueryItemsCompleted(VirtualPage page, AsyncQueryInfo queryInfo, object[] fetchedItems)
        {
            base.OnQueryItemsCompleted(page, queryInfo, fetchedItems);

            Debug.Assert(m_asyncQueryInfosInProgress.Contains(queryInfo));
            m_asyncQueryInfosInProgress.Remove(queryInfo);

            this.UpdateConnectionState();
        }
Beispiel #7
0
        private void AsyncQueryInfo_BeginQueryItems(AsyncQueryInfo queryInfo)
        {
            if (this.IsDisposed)
            {
                return;
            }

            Debug.Assert((this.ParentVirtualList != null) || (this.ParentVirtualList.PagingManager != null));

            this.ParentVirtualList.PagingManager.OnQueryItems(this, queryInfo);
        }
Beispiel #8
0
        private void AsyncQueryInfo_BuiltInAbort(AsyncQueryInfo queryInfo)
        {
            if (this.IsDisposed)
            {
                return;
            }

            Debug.Assert((this.ParentVirtualList != null) || (this.ParentVirtualList.PagingManager != null));

            this.ParentVirtualList.PagingManager.OnBuiltInAbort(this, queryInfo);
            this.IsAborting = false;
        }
Beispiel #9
0
        internal void FillEmptyPage(AsyncQueryInfo asyncQueryInfo, object[] fetchedItems)
        {
            // The VirtualList is disposed or part of a PagingManager that will be disposed (only disconnected when dispose is required)
            if (!this.PagingManager.IsConnected)
            {
                return;
            }

            Debug.Assert(!this.IsDisposed);
            Debug.Assert(!asyncQueryInfo.IsDisposed);

            // We do not want to move the page we are about to fill to the front since it does not count as a legitimate user-acess.  It will get moved to the front when one of its item is accessed.
            VirtualPage page = null;

            page = this.GetPageOrDefaultForItemIndex(asyncQueryInfo.StartIndex, true);

            // Although extremely rare, this situation could occur if we are calling RemovePageNode and the QueryData Dispatcher Operation
            // which has been asyncronously invoked in CreateNewPage is raising the QueryData event at the exact moment when we
            // try to abort the dispatcher operation.  This means that the customer will have queued an async request for data
            // for a page we no longer care about, and have already removed from the Table of Content and our LinkedList.
            // This should NOT occur if the user did not abort the request and called the AsyncQueryInfo EndQuery method since AsyncQueryInfo should
            // not have invoked the EndQueryAction if its ShouldAbort property was set to true.
            if (page == null)
            {
                return;
            }

            Debug.Assert(!page.IsFilled);
            Debug.Assert(this.GetPageStartingIndexForItemIndex(asyncQueryInfo.StartIndex) == asyncQueryInfo.StartIndex);

            Debug.Assert(fetchedItems.Length <= page.Count);

            if (fetchedItems.Length == page.Count)
            {
                object[] oldItems = page.ToItemArray();

                m_tableOfContent.RemovePage(page);

                page.EndQueryItems(asyncQueryInfo, fetchedItems);

                m_tableOfContent.AddPage(page);

                Debug.WriteLineIf(VirtualPageManager.DebugDataVirtualization, "Replaced TOC items/index for page: " + page.ToString());

                this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, fetchedItems, oldItems, asyncQueryInfo.StartIndex));
            }
            else
            {
                // The expected count was not met.  Maybe the user told us the source was bigger than it really is, or maybe there were delete operations made on the source since the last restart.
                // Let's refresh the CollectionView. This will restart the VirtualItemBook and raise the CollectionView's OnCollectionChanged Reset notification.
                this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
            }
        }
    protected internal override void OnQueryItemsCompleted( VirtualPage page, AsyncQueryInfo queryInfo, object[] fetchedItems )
    {
      DataGridVirtualizingQueryableCollectionView collectionView = this.CollectionView as DataGridVirtualizingQueryableCollectionView;

      // The VirtualPageManager was Disposed
      if( collectionView == null )
        return;

      using( collectionView.DeferRefresh() )
      {
        base.OnQueryItemsCompleted( page, queryInfo, fetchedItems );
      }
    }
    protected internal override void OnAbortQueryItems( VirtualPage page, AsyncQueryInfo queryInfo )
    {
      base.OnAbortQueryItems( page, queryInfo );

      // It is possible that the queryInfo was removed previously
      m_asyncQueryInfosInProgress.Remove( queryInfo );

      // In case the page query was aborted when
      // VirtualPageManager.CleanUpUnused is called
      if( page.RemoveAfterOperation )
        this.RemovePage( page );

      this.UpdateConnectionState();
    }
    protected internal override void OnAbortQueryItems( VirtualPage page, AsyncQueryInfo queryInfo )
    {
      DataGridVirtualizingCollectionView collectionView = this.CollectionView as DataGridVirtualizingCollectionView;

      // The VirtualPageManager was Disposed
      if( collectionView == null )
        return;

      DataGridVirtualizingCollectionViewGroup collectionViewGroup = this.GetLinkedCollectionViewGroup( page.ParentVirtualList ) as DataGridVirtualizingCollectionViewGroup;

      collectionView.OnAbortQueryItems( queryInfo, collectionViewGroup );

      base.OnAbortQueryItems( page, queryInfo );
    }
    protected internal override void OnBuiltInAbort( VirtualPage page, AsyncQueryInfo queryInfo )
    {
      // When a built-in abort occurs, we ensure to remove
      // any AsyncQueryInfo from references since the ConnectionState
      // use this array to update its actual state
      m_asyncQueryInfosInProgress.Remove( queryInfo );

      // In case the page query was aborted when
      // VirtualPageManager.CleanUpUnused is called
      if( page.RemoveAfterOperation )
        this.RemovePage( page );

      this.UpdateConnectionState();
    }
        protected internal override void OnQueryItemsCompleted(VirtualPage page, AsyncQueryInfo queryInfo, object[] fetchedItems)
        {
            DataGridVirtualizingQueryableCollectionView collectionView = this.CollectionView as DataGridVirtualizingQueryableCollectionView;

            // The VirtualPageManager was Disposed
            if (collectionView == null)
            {
                return;
            }

            using (collectionView.DeferRefresh())
            {
                base.OnQueryItemsCompleted(page, queryInfo, fetchedItems);
            }
        }
Beispiel #15
0
        private void AsyncQueryInfo_EndQueryItems(AsyncQueryInfo queryInfo, object[] fetchedItems)
        {
            if (this.IsDisposed)
            {
                return;
            }

            Debug.Assert(!this.IsAborting);
            this.ParentVirtualList.PagingManager.OnQueryItemsCompleted(this, queryInfo, fetchedItems);

            if (this.ParentVirtualList.IsRestarting)
            {
                this.Restart();
            }
        }
        internal void OnQueryItems(AsyncQueryInfo asyncQueryInfo, DataGridVirtualizingCollectionViewGroup collectionViewGroup)
        {
            QueryItemsEventArgs e = new QueryItemsEventArgs(this, collectionViewGroup, asyncQueryInfo);

            if (this.QueryItems != null)
            {
                this.QueryItems(this, e);
            }

            DataGridVirtualizingCollectionViewSource source = this.ParentCollectionViewSourceBase as DataGridVirtualizingCollectionViewSource;

            if (source != null)
            {
                source.OnQueryItems(e);
            }
        }
        protected internal override void OnAbortQueryItems(VirtualPage page, AsyncQueryInfo queryInfo)
        {
            DataGridVirtualizingCollectionView collectionView = this.CollectionView as DataGridVirtualizingCollectionView;

            // The VirtualPageManager was Disposed
            if (collectionView == null)
            {
                return;
            }

            DataGridVirtualizingCollectionViewGroup collectionViewGroup = this.GetLinkedCollectionViewGroup(page.ParentVirtualList) as DataGridVirtualizingCollectionViewGroup;

            collectionView.OnAbortQueryItems(queryInfo, collectionViewGroup);

            base.OnAbortQueryItems(page, queryInfo);
        }
Beispiel #18
0
        private void AsyncQueryInfo_QueryErrorChanged(AsyncQueryInfo queryInfo)
        {
            if (this.IsDisposed)
            {
                return;
            }

            Debug.Assert((this.ParentVirtualList != null) || (this.ParentVirtualList.PagingManager != null));

            this.ParentVirtualList.PagingManager.OnQueryErrorChanged(this, queryInfo);

            if (this.ParentVirtualList.IsRestarting)
            {
                this.Restart();
            }
        }
    internal QueryItemsEventArgs(
      DataGridVirtualizingCollectionView collectionView,
      DataGridVirtualizingCollectionViewGroup collectionViewGroup,
      AsyncQueryInfo asyncQueryInfo )
    {
      m_dataGridVirtualizingCollectionView = collectionView;

      // The collectionViewGroup can be null when we abort
      // a QueryItems for the old RootGroup when 
      // DataGridVirtualizingCollectionViewBase.ForceRefresh
      // is called
      m_readonlyGroupPath = ( collectionViewGroup != null )
        ? collectionViewGroup.GroupPath.AsReadOnly()
        : new ReadOnlyCollection<DataGridGroupInfo>( new List<DataGridGroupInfo>() );

      m_asyncQueryInfo = asyncQueryInfo;
    }
Beispiel #20
0
        internal QueryItemsEventArgs(
            DataGridVirtualizingCollectionView collectionView,
            DataGridVirtualizingCollectionViewGroup collectionViewGroup,
            AsyncQueryInfo asyncQueryInfo)
        {
            m_dataGridVirtualizingCollectionView = collectionView;

            // The collectionViewGroup can be null when we abort
            // a QueryItems for the old RootGroup when
            // DataGridVirtualizingCollectionViewBase.ForceRefresh
            // is called
            m_readonlyGroupPath = (collectionViewGroup != null)
        ? collectionViewGroup.GroupPath.AsReadOnly()
        : new ReadOnlyCollection <DataGridGroupInfo>(new List <DataGridGroupInfo>());

            m_asyncQueryInfo = asyncQueryInfo;
        }
Beispiel #21
0
        internal void QueueQueryData(Dispatcher dispatcher)
        {
            Debug.Assert(!this.IsDisposed);
            Debug.Assert(m_asyncQueryInfo == null);

            m_asyncQueryInfo = new AsyncQueryInfo(
                dispatcher,
                new Action <AsyncQueryInfo>(this.AsyncQueryInfo_BeginQueryItems),
                new Action <AsyncQueryInfo>(this.AsyncQueryInfo_AbortQueryItems),
                new Action <AsyncQueryInfo, object[]>(this.AsyncQueryInfo_EndQueryItems),
                new Action <AsyncQueryInfo>(this.AsyncQueryInfo_QueryErrorChanged),
                new Action <AsyncQueryInfo>(this.AsyncQueryInfo_BuiltInAbort),
                m_startDataIndex,
                this.Count);

            m_asyncQueryInfo.QueueQuery();
        }
Beispiel #22
0
        private void AsyncQueryInfo_AbortQueryItems(AsyncQueryInfo queryInfo)
        {
            if (this.IsDisposed)
            {
                return;
            }

            this.ParentVirtualList.PagingManager.OnAbortQueryItems(this, queryInfo);

            this.IsAborting = false;

            // If the page was removed, it was also disposed.
            // This case means the page was not restarting
            if (!this.RemoveAfterOperation && this.ParentVirtualList.IsRestarting)
            {
                this.Restart();
            }
        }
Beispiel #23
0
        public void Dispose()
        {
            Debug.Assert(!this.IsDisposed);

            Debug.Assert((m_asyncCommitInfoList != null) && (m_asyncCommitInfoList.Count == 0), "Some async commit are not completed while disposing VirtualPage");

            if (m_asyncQueryInfo != null)
            {
                // We must dispose the AsyncQueryInfo to be sure
                // it does not root this VirtualPage instance
                m_asyncQueryInfo.Dispose();
                m_asyncQueryInfo = null;
            }

            this.Clear();
            m_parentVirtualList = null;

            this.IsDisposed = true;
        }
Beispiel #24
0
        private void AsyncQueryInfo_EndQueryItems(AsyncQueryInfo queryInfo, object[] fetchedItems)
        {
            if (this.IsDisposed)
            {
                return;
            }

            Debug.Assert((this.ParentVirtualList != null) || (this.ParentVirtualList.PagingManager != null));
            Debug.Assert(!this.IsAborting);

            // The page can be removed when the CollectionView raises a CollectionChanged and the selection is consequently updated, so make sure to lock it until the update operation is done.
            this.LockPage();

            this.ParentVirtualList.PagingManager.OnQueryItemsCompleted(this, queryInfo, fetchedItems);

            this.UnlockPage();

            if (this.ParentVirtualList.IsRestarting)
            {
                this.Restart();
            }
        }
Beispiel #25
0
        internal void EndQueryItems(AsyncQueryInfo asyncQueryInfo, object[] items)
        {
            Debug.Assert(!this.IsDisposed);

            // This can occur when the user notify us that the QueryData is completed for an AsyncQueryInfo.StartIndex that refers to a Page which does exists
            // but that was removed, then re-created thus creating another asyncQueryInfo and queuing another QueryData.
            // The only way to get rid of this situation would be to keep a ref to the queued asyncQueryInfo even if we get rid of the page and re-link the same instance to the newly
            // created page.  This optimization could be done in a future version.  For now, let's return and the second asyncQueryInfo will take care of filling the newly created page.
            if (m_asyncQueryInfo != asyncQueryInfo)
            {
                Debug.Assert(false);

                return;
            }

            if (this.IsFilled)
            {
                throw new InvalidOperationException("An attempt was made to fill a virtual page that is already filled.");
            }

            if (items == null)
            {
                throw new ArgumentNullException("items");
            }

            for (int i = 0; i < items.Length; i++)
            {
                VirtualizedItemInfo virtualizedItemInfo = this[i];

                Debug.Assert(virtualizedItemInfo.DataItem is EmptyDataItem);
                Debug.Assert(virtualizedItemInfo.Index == (m_startDataIndex + i));

                this[i].DataItem = items[i];
            }

            this.IsFilled = true;

            Debug.WriteLineIf(VirtualPageManager.DebugDataVirtualization, "Page Filled - " + this.ToString());
        }
 protected internal abstract void OnBuiltInAbort( VirtualPage virtualPage, AsyncQueryInfo queryInfo );
    internal void OnQueryItems( AsyncQueryInfo asyncQueryInfo, DataGridVirtualizingCollectionViewGroup collectionViewGroup )
    {
      QueryItemsEventArgs e = new QueryItemsEventArgs( this, collectionViewGroup, asyncQueryInfo );

      if( this.QueryItems != null )
        this.QueryItems( this, e );

      DataGridVirtualizingCollectionViewSource source = this.ParentCollectionViewSourceBase as DataGridVirtualizingCollectionViewSource;

      if( source != null )
        source.OnQueryItems( e );
    }
Beispiel #28
0
 private void AsyncQueryInfo_BuiltInAbort(AsyncQueryInfo queryInfo)
 {
     this.ParentVirtualList.PagingManager.OnBuiltInAbort(this, queryInfo);
     this.IsAborting = false;
 }
 protected internal virtual void OnQueryErrorChanged( VirtualPage page, AsyncQueryInfo queryInfo )
 {
 }
    protected internal virtual void OnQueryItemsCompleted( VirtualPage page, AsyncQueryInfo queryInfo, object[] fetchedItems )
    {
      this.IncrementVersion();

      page.ParentVirtualList.FillEmptyPage( queryInfo, fetchedItems );
    }
    protected internal virtual void OnAbortQueryItems( VirtualPage page, AsyncQueryInfo queryInfo )
    {

    }
 protected internal abstract void OnQueryItems( VirtualPage page, AsyncQueryInfo queryInfo );
Beispiel #33
0
 private void AsyncQueryInfo_BeginQueryItems(AsyncQueryInfo queryInfo)
 {
     this.ParentVirtualList.PagingManager.OnQueryItems(this, queryInfo);
 }
 protected internal virtual void OnQueryErrorChanged(VirtualPage page, AsyncQueryInfo queryInfo)
 {
 }
        protected internal virtual void OnQueryItemsCompleted(VirtualPage page, AsyncQueryInfo queryInfo, object[] fetchedItems)
        {
            this.IncrementVersion();

            page.ParentVirtualList.FillEmptyPage(queryInfo, fetchedItems);
        }
 protected internal virtual void OnAbortQueryItems(VirtualPage page, AsyncQueryInfo queryInfo)
 {
 }
 protected internal abstract void OnQueryItems(VirtualPage page, AsyncQueryInfo queryInfo);
 protected internal abstract void OnBuiltInAbort(VirtualPage virtualPage, AsyncQueryInfo queryInfo);
        private void AsyncGatherItems(object workItem)
        {
            object[] parameters = ( object[] )workItem;

            AsyncQueryInfo queryInfo = parameters[0] as AsyncQueryInfo;

            if (queryInfo.ShouldAbort)
            {
                return;
            }

            IQueryable queryable = ( IQueryable )parameters[1];

            object[] items = new object[queryInfo.RequestedItemCount];

            System.Collections.IEnumerator enumerator;

            lock ( m_syncRoot )
            {
                // We reverify here since a reset could have been issued while we were waiting on the lock statement.
                if ((queryInfo.ShouldAbort) || (!this.IsConnected) || (this.IsDisposed))
                {
                    return;
                }

                try
                {
                    Debug.WriteLineIf(VirtualPageManager.DebugDataVirtualization, "Beginning Provider Execute for page at start index: " + queryInfo.StartIndex.ToString());

                    enumerator = queryable.GetEnumerator();

                    Debug.WriteLineIf(VirtualPageManager.DebugDataVirtualization, "Ended Provider Execute for page at start index: " + queryInfo.StartIndex.ToString());

                    int i = 0;

                    while (enumerator.MoveNext())
                    {
                        object current = enumerator.Current;

                        if (current != null)
                        {
                            items[i] = enumerator.Current;
                        }

                        i++;
                    }
                }
                catch (Exception exception)
                {
                    // TimeOut exeception or other.
                    queryInfo.AbortQuery();
                    queryInfo.Error = exception.Message;
                    return;
                }
            }

            bool queryableWasReversed = ( bool )parameters[2];

            if (queryableWasReversed)
            {
                Array.Reverse(items);
            }

            queryInfo.EndQuery(items);
        }
        private void AsyncGatherItems(object workItem)
        {
            object[] parameters = ( object[] )workItem;

            AsyncQueryInfo queryInfo = parameters[0] as AsyncQueryInfo;

            if (queryInfo.ShouldAbort)
            {
                return;
            }

            IQueryable queryable          = ( IQueryable )parameters[1];
            int        requestedItemCount = queryInfo.RequestedItemCount;

            object[] items = new object[requestedItemCount];

            System.Collections.IEnumerator enumerator;

            lock ( m_syncRoot )
            {
                // We reverify here since a reset could have been issued while we were waiting on the lock statement.
                if ((queryInfo.ShouldAbort) || (!this.IsConnected) || (this.IsDisposed))
                {
                    return;
                }

                try
                {
                    Debug.WriteLineIf(VirtualPageManager.DebugDataVirtualization, "Beginning Provider Execute for page at start index: " + queryInfo.StartIndex.ToString());

                    enumerator = queryable.GetEnumerator();

                    Debug.WriteLineIf(VirtualPageManager.DebugDataVirtualization, "Ended Provider Execute for page at start index: " + queryInfo.StartIndex.ToString());

                    int i = 0;

                    while (enumerator.MoveNext() && (i < requestedItemCount))
                    {
                        object current = enumerator.Current;

                        if (current != null)
                        {
                            items[i] = enumerator.Current;
                            i++;
                        }
                    }
                }
                catch (Exception exception)
                {
                    // TimeOut exeception or other.
                    queryInfo.AbortQuery();
                    queryInfo.Error = exception.Message;
                    return;
                }
            }

            items = items.Where(item => item != null).ToArray();

            try
            {
                if (items.Count() != requestedItemCount)
                {
                    throw new InvalidOperationException("The number of non-null items returned by the source must be equal to the provided item count.");
                }
            }
            catch
            {
                //go silently here, in case the next sequance give a valid result.  At the same time, if it does not, the dev has information when debugging.
            }

            bool queryableWasReversed = ( bool )parameters[2];

            if (queryableWasReversed)
            {
                Array.Reverse(items);
            }

            queryInfo.EndQuery(items);
        }