Exemplo n.º 1
0
        /// <summary>
        /// Partially fill out BreakRecordTable by pre-calculating BreakRecords.
        /// This callback is invoked when background pagination is enabled and
        /// BreakRecordTable is not completely updated yet.
        /// </summary>
        private object OnBackgroundPagination(object arg)
        {
            DateTime dtStart = DateTime.Now;
            DateTime dtStop;

            _backgroundPaginationOperation = null; // Clear out pending request.

            // Ensure usage from just one Dispatcher object.
            // FlowDocumentPaginator runs its own layout, hence there is a need
            // to protect it from random access from other threads.
            _dispatcherObject.VerifyAccess();

            // Detect reentrancy.
            if (_document.StructuralCache.IsFormattingInProgress)
            {
                throw new InvalidOperationException(SR.Get(SRID.FlowDocumentFormattingReentrancy));
            }

            // Ignore this formatting request, if the element was already disposed.
            if (_document.StructuralCache.PtsContext.Disposed)
            {
                return(null);
            }


            // Disable processing of the queue during blocking operations to prevent unrelated reentrancy.
            using (_document.Dispatcher.DisableProcessing())
            {
                _document.StructuralCache.IsFormattingInProgress = true; // Set reentrancy flag
                try
                {
                    for (int index = 0; index < _asyncRequests.Count; index++)
                    {
                        AsyncRequest asyncRequest = _asyncRequests[index];

                        if (asyncRequest.Process())
                        {
                            _asyncRequests.RemoveAt(index);
                            index--; // Offset the index add
                        }
                    }

                    dtStop = DateTime.Now;

                    if (_backgroundPagination && !_brt.IsClean)
                    {
                        // Calculate BreakRecords until entire content is calculated or
                        // specific time span has been exceeded (_paginationTimeout).
                        while (!_brt.IsClean)
                        {
                            // Get the first invalid entry in the BreakRecordTable, calculate
                            // BreakRecord for it and update BreakRecordTable with the calculated
                            // value.
                            FormatPage(_brt.Count);

                            // Update time span.
                            dtStop = DateTime.Now;
                            long timeSpan = (dtStop.Ticks - dtStart.Ticks) / TimeSpan.TicksPerMillisecond;

                            if (timeSpan > _paginationTimeout)
                            {
                                break;
                            }
                        }

                        // Initiate the next async operation.
                        InitiateNextAsyncOperation();
                    }
                }
                finally
                {
                    _document.StructuralCache.IsFormattingInProgress = false;    // Clear reentrancy flag.
                }
            }

            return(null);
        }