Beispiel #1
0
        public static object Load(System.Xaml.XamlReader reader)
        {
            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }
            object root = null;

            try
            {
                root = Load(reader, null);
            }
            catch (Exception e)
            {
                IUriContext uriContext = reader as IUriContext;
                Uri         baseUri    = (uriContext != null) ? uriContext.BaseUri : null;
                // Don't wrap critical exceptions or already-wrapped exceptions.
                if (MS.Internal.CriticalExceptions.IsCriticalException(e) || !ShouldReWrapException(e, baseUri))
                {
                    throw;
                }
                RewrapException(e, baseUri);
            }
            finally
            {
                if (TraceMarkup.IsEnabled)
                {
                    TraceMarkup.Trace(TraceEventType.Stop, TraceMarkup.Load, root);
                }

                EventTrace.EasyTraceEvent(EventTrace.Keyword.KeywordXamlBaml, EventTrace.Event.WClientParseXmlEnd);

#if DEBUG_CLR_MEM
                if (clrTracingEnabled && (CLRProfilerControl.CLRLoggingLevel >= CLRProfilerControl.CLRLogState.Performance))
                {
                    CLRProfilerControl.CLRLogWriteLine("End_XamlParse_{0}", pass);
                }
#endif // DEBUG_CLR_MEM
            }
            return(root);
        }
Beispiel #2
0
        //[CodeAnalysis("AptcaMethodsShouldOnlyCallAptcaMethods")] //Tracking Bug: 29647
        internal static object LoadBaml(
            Stream stream,
            ParserContext parserContext,
            object parent,
            bool closeStream)
        {
            object root = null;

#if DEBUG_CLR_MEM
            bool clrTracingEnabled = false;
            // Use local pass variable to correctly log nested parses.
            int pass = 0;

            if (CLRProfilerControl.ProcessIsUnderCLRProfiler &&
                (CLRProfilerControl.CLRLoggingLevel >= CLRProfilerControl.CLRLogState.Performance))
            {
                clrTracingEnabled = true;
                pass = ++_CLRBamlPass;
                CLRProfilerControl.CLRLogWriteLine("Begin_BamlParse_{0}", pass);
            }
#endif // DEBUG_CLR_MEM

            EventTrace.EasyTraceEvent(EventTrace.Keyword.KeywordXamlBaml | EventTrace.Keyword.KeywordPerf, EventTrace.Event.WClientParseBamlBegin, parserContext.BaseUri);

            if (TraceMarkup.IsEnabled)
            {
                TraceMarkup.Trace(TraceEventType.Start, TraceMarkup.Load);
            }

            try
            {
                //
                // If the stream contains info about the Assembly that created it,
                // set StreamCreatedAssembly from the stream instance.
                //
                IStreamInfo streamInfo = stream as IStreamInfo;
                if (streamInfo != null)
                {
                    parserContext.StreamCreatedAssembly = streamInfo.Assembly;
                }

                Baml2006ReaderSettings readerSettings = XamlReader.CreateBamlReaderSettings();
                readerSettings.BaseUri       = parserContext.BaseUri;
                readerSettings.LocalAssembly = streamInfo.Assembly;
                // We do not set OwnsStream = true so the Baml2006Reader will not close the stream.
                // Calling code is responsible for disposing the stream
                if (readerSettings.BaseUri == null || String.IsNullOrEmpty(readerSettings.BaseUri.ToString()))
                {
                    readerSettings.BaseUri = BaseUriHelper.PackAppBaseUri;
                }

                var reader = new Baml2006ReaderInternal(stream, new Baml2006SchemaContext(readerSettings.LocalAssembly), readerSettings, parent);

                // We don't actually use the GeneratedInternalTypeHelper any more.
                // But for v3 compat, don't allow loading of internals in PT unless there is one.
                Type internalTypeHelper = null;
                if (streamInfo.Assembly != null)
                {
                    try
                    {
                        internalTypeHelper = XamlTypeMapper.GetInternalTypeHelperTypeFromAssembly(parserContext);
                    }
                    // This can perform attribute reflection which will fail if the assembly has unresolvable
                    // attributes. If that happens, just assume there is no helper.
                    catch (Exception e)
                    {
                        if (MS.Internal.CriticalExceptions.IsCriticalException(e))
                        {
                            throw;
                        }
                    }
                }

                if (internalTypeHelper != null)
                {
                    XamlAccessLevel    accessLevel    = XamlAccessLevel.AssemblyAccessTo(streamInfo.Assembly);
                    XamlLoadPermission loadPermission = new XamlLoadPermission(accessLevel);
                    loadPermission.Assert();
                    try
                    {
                        root = WpfXamlLoader.LoadBaml(reader, parserContext.SkipJournaledProperties, parent, accessLevel, parserContext.BaseUri);
                    }
                    finally
                    {
                        CodeAccessPermission.RevertAssert();
                    }
                }
                else
                {
                    root = WpfXamlLoader.LoadBaml(reader, parserContext.SkipJournaledProperties, parent, null, parserContext.BaseUri);
                }

                DependencyObject dObject = root as DependencyObject;
                if (dObject != null)
                {
                    dObject.SetValue(BaseUriHelper.BaseUriProperty, readerSettings.BaseUri);
                }

                Application app = root as Application;
                if (app != null)
                {
                    app.ApplicationMarkupBaseUri = GetBaseUri(readerSettings.BaseUri);
                }

                Debug.Assert(parent == null || root == parent);
            }

            finally
            {
                if (TraceMarkup.IsEnabled)
                {
                    TraceMarkup.Trace(TraceEventType.Stop, TraceMarkup.Load, root);
                }

                EventTrace.EasyTraceEvent(EventTrace.Keyword.KeywordXamlBaml | EventTrace.Keyword.KeywordPerf, EventTrace.Event.WClientParseBamlEnd, parserContext.BaseUri);

                if (closeStream && stream != null)
                {
                    stream.Close();
                }

#if DEBUG_CLR_MEM
                if (clrTracingEnabled && (CLRProfilerControl.CLRLoggingLevel >= CLRProfilerControl.CLRLogState.Performance))
                {
                    CLRProfilerControl.CLRLogWriteLine("End_BamlParse_{0}", pass);
                }
#endif // DEBUG_CLR_MEM
            }

            return(root);
        }
Beispiel #3
0
        /// <summary>
        /// Render method renders the visual tree.
        /// </summary>
        void ICompositionTarget.Render(bool inResize, DUCE.Channel channel)
        {
#if DEBUG_CLR_MEM
            bool clrTracingEnabled = false;

            if (CLRProfilerControl.ProcessIsUnderCLRProfiler &&
                (CLRProfilerControl.CLRLoggingLevel >= CLRProfilerControl.CLRLogState.Performance))
            {
                clrTracingEnabled = true;
                ++_renderCLRPass;
                CLRProfilerControl.CLRLogWriteLine("Begin_FullRender_{0}", _renderCLRPass);
            }
#endif // DEBUG_CLR_MEM

            //
            // Now we render the scene
            //

#if MEDIA_PERFORMANCE_COUNTERS
            _frameRateTimer.Begin();
#endif

            if (_rootVisual.Value != null)
            {
                bool etwTracingEnabled = false;

                if (EventTrace.IsEnabled(EventTrace.Keyword.KeywordGeneral | EventTrace.Keyword.KeywordPerf, EventTrace.Level.Info))
                {
                    etwTracingEnabled = true;
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientPrecomputeSceneBegin, EventTrace.Keyword.KeywordGraphics | EventTrace.Keyword.KeywordPerf, EventTrace.Level.Info, PerfService.GetPerfElementID(this));
                }

#if MEDIA_PERFORMANCE_COUNTERS
                _precomputeRateTimer.Begin();
#endif
                // precompute is channel agnostic
                _rootVisual.Value.Precompute();

#if MEDIA_PERFORMANCE_COUNTERS
                _precomputeRateTimer.End();
#endif

                if (etwTracingEnabled)
                {
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientPrecomputeSceneEnd, EventTrace.Keyword.KeywordGraphics | EventTrace.Keyword.KeywordPerf, EventTrace.Level.Info);
                }

#if DEBUG
                MediaTrace.RenderPass.Trace("Full Update");
#endif

                if (etwTracingEnabled)
                {
                    EventTrace.EventProvider.TraceEvent(
                        EventTrace.Event.WClientCompileSceneBegin, EventTrace.Keyword.KeywordGraphics | EventTrace.Keyword.KeywordPerf, EventTrace.Level.Info, PerfService.GetPerfElementID(this));
                }

#if MEDIA_PERFORMANCE_COUNTERS
                _renderRateTimer.Begin();
#endif

                Compile(channel);

#if MEDIA_PERFORMANCE_COUNTERS
                _renderRateTimer.End();
#endif

                if (etwTracingEnabled)
                {
                    EventTrace.EventProvider.TraceEvent(
                        EventTrace.Event.WClientCompileSceneEnd, EventTrace.Keyword.KeywordGraphics | EventTrace.Keyword.KeywordPerf, EventTrace.Level.Info);
                }
            }

#if DEBUG_CLR_MEM
            if (clrTracingEnabled &&
                CLRProfilerControl.CLRLoggingLevel >= CLRProfilerControl.CLRLogState.Performance)
            {
                CLRProfilerControl.CLRLogWriteLine("End_FullRender_{0}", _renderCLRPass);
            }
#endif // DEBUG_CLR_MEM



#if MEDIA_PERFORMANCE_COUNTERS
            _frameRateTimer.End();
            System.Console.WriteLine("RENDERING PERFORMANCE DATA");
            System.Console.WriteLine("Frame rendering time:  " + _frameRateTimer.TimeOfLastPeriod + "ms");
            System.Console.WriteLine("Frame precompute time: " + _precomputeRateTimer.TimeOfLastPeriod + "ms");
            System.Console.WriteLine("Frame render time:     " + _renderRateTimer.TimeOfLastPeriod + "ms");
#endif
        }
Beispiel #4
0
        /// <summary>
        /// Reads XAML from the passed stream, building an object tree and returning the
        /// root of that tree.  Wrap a CompatibilityReader with another XmlReader that
        /// uses the passed reader settings to allow validation of xaml.
        /// </summary>
        /// <param name="reader">XmlReader to use.  This is NOT wrapped by any
        ///  other reader</param>
        /// <param name="context">Optional parser context.  May be null </param>
        /// <param name="parseMode">Sets synchronous or asynchronous parsing</param>
        /// <returns>object root generated after xml parsed</returns>
        // Note this is the internal entry point for XPS.  XPS calls here so
        // its reader is not wrapped with a Markup Compat Reader.
        internal static object Load(
            XmlReader reader,
            ParserContext parserContext,
            XamlParseMode parseMode)
        {
            if (parseMode == XamlParseMode.Uninitialized ||
                parseMode == XamlParseMode.Asynchronous)
            {
                XamlReader xamlReader = new XamlReader();
                return(xamlReader.LoadAsync(reader, parserContext));
            }

            if (parserContext == null)
            {
                parserContext = new ParserContext();
            }

#if DEBUG_CLR_MEM
            bool clrTracingEnabled = false;
            // Use local pass variable to correctly log nested parses.
            int pass = 0;

            if (CLRProfilerControl.ProcessIsUnderCLRProfiler &&
                (CLRProfilerControl.CLRLoggingLevel >= CLRProfilerControl.CLRLogState.Performance))
            {
                clrTracingEnabled = true;
                pass = ++_CLRXamlPass;
                CLRProfilerControl.CLRLogWriteLine("Begin_XamlParse_{0}", pass);
            }
#endif // DEBUG_CLR_MEM

            EventTrace.EasyTraceEvent(EventTrace.Keyword.KeywordXamlBaml, EventTrace.Event.WClientParseXmlBegin, parserContext.BaseUri);

            if (TraceMarkup.IsEnabled)
            {
                TraceMarkup.Trace(TraceEventType.Start, TraceMarkup.Load);
            }
            object root = null;
            try
            {
                if (parserContext.BaseUri == null ||
                    String.IsNullOrEmpty(parserContext.BaseUri.ToString()))
                {
                    if (reader.BaseURI == null ||
                        String.IsNullOrEmpty(reader.BaseURI.ToString()))
                    {
                        parserContext.BaseUri = BaseUriHelper.PackAppBaseUri;
                    }
                    else
                    {
                        parserContext.BaseUri = new Uri(reader.BaseURI);
                    }
                }

                System.Xaml.XamlXmlReaderSettings settings = new System.Xaml.XamlXmlReaderSettings();
                settings.IgnoreUidsOnPropertyElements = true;
                settings.BaseUri         = parserContext.BaseUri;
                settings.ProvideLineInfo = true;

                XamlSchemaContext schemaContext = parserContext.XamlTypeMapper != null ?
                                                  parserContext.XamlTypeMapper.SchemaContext : GetWpfSchemaContext();
                System.Xaml.XamlXmlReader xamlXmlReader = new System.Xaml.XamlXmlReader(reader, schemaContext, settings);
                root = Load(xamlXmlReader, parserContext);
                reader.Close();
            }
            catch (Exception e)
            {
                // Don't wrap critical exceptions or already-wrapped exceptions.
                if (MS.Internal.CriticalExceptions.IsCriticalException(e) || !ShouldReWrapException(e, parserContext.BaseUri))
                {
                    throw;
                }
                RewrapException(e, parserContext.BaseUri);
            }
            finally
            {
                if (TraceMarkup.IsEnabled)
                {
                    TraceMarkup.Trace(TraceEventType.Stop, TraceMarkup.Load, root);
                }

                EventTrace.EasyTraceEvent(EventTrace.Keyword.KeywordXamlBaml, EventTrace.Event.WClientParseXmlEnd, parserContext.BaseUri);

#if DEBUG_CLR_MEM
                if (clrTracingEnabled && (CLRProfilerControl.CLRLoggingLevel >= CLRProfilerControl.CLRLogState.Performance))
                {
                    CLRProfilerControl.CLRLogWriteLine("End_XamlParse_{0}", pass);
                }
#endif // DEBUG_CLR_MEM
            }
            return(root);
        }
Beispiel #5
0
        /// <summary>
        /// Tells ContextLayoutManager to finalize possibly async update.
        /// Used before accessing services off Visual.
        /// </summary>

        //[CodeAnalysis("AptcaMethodsShouldOnlyCallAptcaMethods")] //Tracking
        internal void UpdateLayout()
        {
            VerifyAccess();

            //make UpdateLayout to be a NOP if called during UpdateLayout.
            if (_isInUpdateLayout ||
                _measuresOnStack > 0 ||
                _arrangesOnStack > 0 ||
                _isDead)
            {
                return;
            }

#if DEBUG_CLR_MEM
            bool clrTracingEnabled = false;

            // Start over with the Measure and arrange counters for this layout pass
            int measureCLRPass = 0;
            int arrangeCLRPass = 0;

            if (CLRProfilerControl.ProcessIsUnderCLRProfiler)
            {
                clrTracingEnabled = true;
                if (CLRProfilerControl.CLRLoggingLevel >= CLRProfilerControl.CLRLogState.Performance)
                {
                    ++_layoutCLRPass;
                    CLRProfilerControl.CLRLogWriteLine("Begin_Layout_{0}", _layoutCLRPass);
                }
            }
#endif // DEBUG_CLR_MEM

            bool etwTracingEnabled = false;
            long perfElementID     = 0;
            const EventTrace.Keyword etwKeywords = EventTrace.Keyword.KeywordLayout | EventTrace.Keyword.KeywordPerf;
            if (!_isUpdating && EventTrace.IsEnabled(etwKeywords, EventTrace.Level.Info))
            {
                etwTracingEnabled = true;
                perfElementID     = PerfService.GetPerfElementID(this);
                EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientLayoutBegin, etwKeywords, EventTrace.Level.Info,
                                                    perfElementID, EventTrace.LayoutSource.LayoutManager);
            }

            int       cnt            = 0;
            bool      gotException   = true;
            UIElement currentElement = null;

            try
            {
                invalidateTreeIfRecovering();


                while (hasDirtiness || _firePostLayoutEvents)
                {
                    if (++cnt > 153)
                    {
                        //loop detected. Lets go over to background to let input/user to correct the situation.
                        //most frequently, we get such a loop as a result of input detecting a mouse in the "bad spot"
                        //and some event handler oscillating a layout-affecting property depending on hittest result
                        //of the mouse. Going over to background will not break the loopp but will allow user to
                        //move the mouse so that it goes out of the "bad spot".
                        Dispatcher.BeginInvoke(DispatcherPriority.Background, _updateLayoutBackground, this);
                        currentElement = null;
                        gotException   = false;
                        if (etwTracingEnabled)
                        {
                            EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientLayoutAbort, etwKeywords, EventTrace.Level.Info, 0, cnt);
                        }
                        return;
                    }


                    //this flag stops posting update requests to MediaContext - we are already in one
                    //note that _isInUpdateLayout is close but different - _isInUpdateLayout is reset
                    //before firing LayoutUpdated so that event handlers could call UpdateLayout but
                    //still could not cause posting of MediaContext work item. Posting MediaContext workitem
                    //causes infinite loop in MediaContext.
                    _isUpdating       = true;
                    _isInUpdateLayout = true;

#if DEBUG_CLR_MEM
                    if (clrTracingEnabled && (CLRProfilerControl.CLRLoggingLevel >= CLRProfilerControl.CLRLogState.Verbose))
                    {
                        ++measureCLRPass;
                        CLRProfilerControl.CLRLogWriteLine("Begin_Measure_{0}_{1}", _layoutCLRPass, measureCLRPass);
                    }
#endif // DEBUG_CLR_MEM

                    if (etwTracingEnabled)
                    {
                        EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientMeasureBegin, etwKeywords, EventTrace.Level.Info, perfElementID);
                    }

                    // Disable processing of the queue during blocking operations to prevent unrelated reentrancy.
                    using (Dispatcher.DisableProcessing())
                    {
                        //loop for Measure
                        //We limit the number of loops here by time - normally, all layout
                        //calculations should be done by this time, this limit is here for
                        //emergency, "infinite loop" scenarios - yielding in this case will
                        //provide user with ability to continue to interact with the app, even though
                        //it will be sluggish. If we don't yield here, the loop is goign to be a deadly one
                        //and it will be impossible to save results or even close the window.
                        int      loopCounter   = 0;
                        DateTime loopStartTime = new DateTime(0);
                        while (true)
                        {
                            if (++loopCounter > 153)
                            {
                                loopCounter = 0;
                                //first bunch of iterations is free, then we start count time
                                //this way, we don't call DateTime.Now in most layout updates
                                if (loopStartTime.Ticks == 0)
                                {
                                    loopStartTime = DateTime.UtcNow;
                                }
                                else
                                {
                                    TimeSpan loopDuration = (DateTime.UtcNow - loopStartTime);
                                    if (loopDuration.Milliseconds > 153 * 2) // 153*2 = magic*science
                                    {
                                        //loop detected. Lets go over to background to let input work.
                                        Dispatcher.BeginInvoke(DispatcherPriority.Background, _updateLayoutBackground, this);
                                        currentElement = null;
                                        gotException   = false;
                                        if (etwTracingEnabled)
                                        {
                                            EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientMeasureAbort, etwKeywords, EventTrace.Level.Info,
                                                                                loopDuration.Milliseconds, loopCounter);
                                        }
                                        return;
                                    }
                                }
                            }

                            currentElement = MeasureQueue.GetTopMost();

                            if (currentElement == null)
                            {
                                break;                        //exit if no more Measure candidates
                            }
                            currentElement.Measure(currentElement.PreviousConstraint);
//dmitryt,
                        }

                        if (etwTracingEnabled)
                        {
                            EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientMeasureEnd, etwKeywords, EventTrace.Level.Info, loopCounter);
                            EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientArrangeBegin, etwKeywords, EventTrace.Level.Info, perfElementID);
                        }


#if DEBUG_CLR_MEM
                        if (clrTracingEnabled && (CLRProfilerControl.CLRLoggingLevel >= CLRProfilerControl.CLRLogState.Verbose))
                        {
                            CLRProfilerControl.CLRLogWriteLine("End_Measure_{0}_{1}", _layoutCLRPass, measureCLRPass);
                            ++arrangeCLRPass;
                            CLRProfilerControl.CLRLogWriteLine("Begin_Arrange_{0}_{1}", _layoutCLRPass, arrangeCLRPass);
                        }
#endif // DEBUG_CLR_MEM

                        //loop for Arrange
                        //if Arrange dirtied the tree go clean it again

                        //We limit the number of loops here by time - normally, all layout
                        //calculations should be done by this time, this limit is here for
                        //emergency, "infinite loop" scenarios - yielding in this case will
                        //provide user with ability to continue to interact with the app, even though
                        //it will be sluggish. If we don't yield here, the loop is goign to be a deadly one
                        //and it will be impossible to save results or even close the window.
                        loopCounter   = 0;
                        loopStartTime = new DateTime(0);
                        while (MeasureQueue.IsEmpty)
                        {
                            if (++loopCounter > 153)
                            {
                                loopCounter = 0;
                                //first bunch of iterations is free, then we start count time
                                //this way, we don't call DateTime.Now in most layout updates
                                if (loopStartTime.Ticks == 0)
                                {
                                    loopStartTime = DateTime.UtcNow;
                                }
                                else
                                {
                                    TimeSpan loopDuration = (DateTime.UtcNow - loopStartTime);
                                    if (loopDuration.Milliseconds > 153 * 2) // 153*2 = magic*science
                                    {
                                        //loop detected. Lets go over to background to let input work.
                                        Dispatcher.BeginInvoke(DispatcherPriority.Background, _updateLayoutBackground, this);
                                        currentElement = null;
                                        gotException   = false;
                                        if (etwTracingEnabled)
                                        {
                                            EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientArrangeAbort, etwKeywords, EventTrace.Level.Info,
                                                                                loopDuration.Milliseconds, loopCounter);
                                        }
                                        return;
                                    }
                                }
                            }

                            currentElement = ArrangeQueue.GetTopMost();

                            if (currentElement == null)
                            {
                                break;                        //exit if no more Measure candidates
                            }
                            Rect finalRect = getProperArrangeRect(currentElement);

                            currentElement.Arrange(finalRect);
//dmitryt,
                        }

                        if (etwTracingEnabled)
                        {
                            EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientArrangeEnd, etwKeywords, EventTrace.Level.Info, loopCounter);
                        }

#if DEBUG_CLR_MEM
                        if (clrTracingEnabled && (CLRProfilerControl.CLRLoggingLevel >= CLRProfilerControl.CLRLogState.Verbose))
                        {
                            CLRProfilerControl.CLRLogWriteLine("End_Arrange_{0}_{1}", _layoutCLRPass, arrangeCLRPass);
                        }
#endif // DEBUG_CLR_MEM

                        //if Arrange dirtied the tree go clean it again
                        //it is not neccesary to check ArrangeQueue sicnce we just exited from Arrange loop
                        if (!MeasureQueue.IsEmpty)
                        {
                            continue;
                        }

                        //let LayoutUpdated handlers to call UpdateLayout
                        //note that it means we can get reentrancy into UpdateLayout past this point,
                        //if any of event handlers call UpdateLayout sync. Need to protect from reentrancy
                        //in the firing methods below.
                        _isInUpdateLayout = false;
                    }

                    fireSizeChangedEvents();
                    if (hasDirtiness)
                    {
                        continue;
                    }
                    fireLayoutUpdateEvent();
                    if (hasDirtiness)
                    {
                        continue;
                    }
                    fireAutomationEvents();
                    if (hasDirtiness)
                    {
                        continue;
                    }
                    fireSizeChangedEvents(); // if nothing is dirty, one last chance for any size changes to announce.
                }

                currentElement = null;
                gotException   = false;
            }
            finally
            {
                _isUpdating          = false;
                _layoutRequestPosted = false;
                _isInUpdateLayout    = false;

                if (gotException)
                {
                    if (etwTracingEnabled)
                    {
                        EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientLayoutException, etwKeywords, EventTrace.Level.Info, PerfService.GetPerfElementID(currentElement));
                    }

                    //set indicator
                    _gotException       = true;
                    _forceLayoutElement = currentElement;

                    //make attempt to request the subsequent layout calc
                    //some exception handler schemas use Idle priorities to
                    //wait until dust settles. Then they correct the issue noted in the exception handler.
                    //We don't want to attempt to re-do the operation on the priority higher then that.
                    Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, _updateLayoutBackground, this);
                }
            }

            MS.Internal.Text.TextInterface.Font.ResetFontFaceCache();
            MS.Internal.FontCache.BufferCache.Reset();

            if (etwTracingEnabled)
            {
                EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientLayoutEnd, etwKeywords, EventTrace.Level.Info);
            }

#if DEBUG_CLR_MEM
            if (clrTracingEnabled && (CLRProfilerControl.CLRLoggingLevel >= CLRProfilerControl.CLRLogState.Performance))
            {
                CLRProfilerControl.CLRLogWriteLine("End_Layout_{0}", _layoutCLRPass);
            }
#endif // DEBUG_CLR_MEM
        }