public void UpdateLayout() { base.VerifyAccess(); if (!this._isUpdating) { this._isUpdating = true; WindowManager.Instance.Invalidate(); LayoutQueue measureQueue = this.MeasureQueue; LayoutQueue arrangeQueue = this.ArrangeQueue; int num = 0; bool flag = true; UIElement parent = null; try { this.invalidateTreeIfRecovering(); while (!this.MeasureQueue.IsEmpty || !this.ArrangeQueue.IsEmpty) { if (++num > 0x99) { base.Dispatcher.BeginInvoke(this._updateLayoutBackground, this); parent = null; flag = false; return; } int num2 = 0; long loopStartTime = 0L; Label_0070: if (++num2 > 0x99) { num2 = 0; if (this.LimitExecution(ref loopStartTime)) { parent = null; flag = false; return; } } parent = measureQueue.GetTopMost(); if (parent != null) { parent.Measure(parent._previousAvailableWidth, parent._previousAvailableHeight); measureQueue.RemoveOrphans(parent); goto Label_0070; } num2 = 0; loopStartTime = 0L; Label_00C7: if (++num2 > 0x99) { num2 = 0; if (this.LimitExecution(ref loopStartTime)) { parent = null; flag = false; return; } } parent = arrangeQueue.GetTopMost(); if (parent != null) { int num4; int num5; int num6; int num7; this.getProperArrangeRect(parent, out num4, out num5, out num6, out num7); parent.Arrange(num4, num5, num6, num7); arrangeQueue.RemoveOrphans(parent); goto Label_00C7; } } parent = null; flag = false; } finally { this._isUpdating = false; this._layoutRequestPosted = false; if (flag) { this._gotException = true; this._forceLayoutElement = parent; base.Dispatcher.BeginInvoke(this._updateLayoutBackground, this); } } } }
public void UpdateLayout() { VerifyAccess(); //make UpdateLayout to be a NOP if called during UpdateLayout. if (_isUpdating) { return; } _isUpdating = true; WindowManager.Instance.Invalidate(); LayoutQueue measureQueue = MeasureQueue; LayoutQueue arrangeQueue = ArrangeQueue; int cnt = 0; bool gotException = true; UIElement currentElement = null; //NOTE: // //There are a bunch of checks here that break out of and re-queue layout if //it looks like things are taking too long or we have somehow gotten into an //infinite loop. In the TinyCLR we will probably have better ways of //dealing with a bad app through app domain separation, but keeping this //robustness can't hurt. In a single app domain scenario, it could //give the opportunity to get out to the system if something is misbehaving, //we like this kind of reliability in embedded systems. // try { invalidateTreeIfRecovering(); while ((!MeasureQueue.IsEmpty) || (!ArrangeQueue.IsEmpty)) { if (++cnt > 153) { //loop detected. Lets re-queue and let input/user to correct the situation. // Dispatcher.BeginInvoke(_updateLayoutBackground, this); currentElement = null; gotException = false; return; } //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 int loopCounter = 0; TimeSpan loopStartTime = TimeSpan.Zero; while (true) { if (++loopCounter > 153) { loopCounter = 0; if (LimitExecution(ref loopStartTime)) { currentElement = null; gotException = false; return; } } currentElement = measureQueue.GetTopMost(); if (currentElement == null) { break; //exit if no more Measure candidates } currentElement.Measure( currentElement._previousAvailableWidth, currentElement._previousAvailableHeight ); measureQueue.RemoveOrphans(currentElement); } //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 loopCounter = 0; loopStartTime = TimeSpan.Zero; while (true) { if (++loopCounter > 153) { loopCounter = 0; if (LimitExecution(ref loopStartTime)) { currentElement = null; gotException = false; return; } } currentElement = arrangeQueue.GetTopMost(); if (currentElement == null) { break; //exit if no more Arrange candidates } int arrangeX, arrangeY, arrangeWidth, arrangeHeight; getProperArrangeRect(currentElement, out arrangeX, out arrangeY, out arrangeWidth, out arrangeHeight); #if TINYCLR_DEBUG_LAYOUT Trace.Print("arrangeWidth = " + arrangeWidth); Trace.Print("arrangeHeight = " + arrangeWidth); #endif currentElement.Arrange(arrangeX, arrangeY, arrangeWidth, arrangeHeight); arrangeQueue.RemoveOrphans(currentElement); } /* REFACTOR -- do we need Layout events and Size changed events? * * //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. * * fireSizeChangedEvents(); * if ((!MeasureQueue.IsEmpty) || (!ArrangeQueue.IsEmpty)) continue; * fireLayoutUpdateEvent(); */ } currentElement = null; gotException = false; } finally { _isUpdating = false; _layoutRequestPosted = false; if (gotException) { //set indicator _gotException = true; _forceLayoutElement = currentElement; //make attempt to request the subsequent layout calc Dispatcher.BeginInvoke(_updateLayoutBackground, this); } } }