private bool WaitForOffsetToSettle(Edit text, double millisecondsTimeout, bool failOnError) { Wait.ForIdle(); const double millisecondsNormalStepTimeout = 100; const double millisecondsIdleStepTimeout = 600; ValueChangedEventWaiter waiter = new ValueChangedEventWaiter(text); int unsuccessfulWaits = 0; int maxUnsuccessfulWaits = (int)(millisecondsIdleStepTimeout / millisecondsNormalStepTimeout); Log.Comment("Original State: " + elements.GetScrollViewerStateTextBox().GetText()); Log.Comment("Original Offset: " + text.Value); // When the initial State is still Idle, use a longer timeout to allow it to transition out of Idle. double millisecondsWait = (elements.GetScrollViewerStateTextBox().GetText() == "Idle") ? millisecondsIdleStepTimeout : millisecondsNormalStepTimeout; double millisecondsCumulatedWait = 0; do { Log.Comment("Waiting for Offset change."); waiter.Reset(); if (waiter.TryWait(TimeSpan.FromMilliseconds(millisecondsWait))) { unsuccessfulWaits = 0; } else { unsuccessfulWaits++; } millisecondsCumulatedWait += millisecondsWait; millisecondsWait = millisecondsNormalStepTimeout; Log.Comment("Current State: " + elements.GetScrollViewerStateTextBox().GetText()); Log.Comment("Current Offset: " + text.Value); Wait.ForIdle(); }while (elements.GetScrollViewerStateTextBox().GetText() != "Idle" && millisecondsCumulatedWait < millisecondsTimeout && unsuccessfulWaits <= maxUnsuccessfulWaits); if (elements.GetScrollViewerStateTextBox().GetText() == "Idle") { Log.Comment("Idle State reached after " + millisecondsCumulatedWait + " out of " + millisecondsTimeout + " milliseconds. Final Offset: " + text.Value); return(true); } else { string message = unsuccessfulWaits > maxUnsuccessfulWaits ? "Offset has not changed within " + millisecondsIdleStepTimeout + " milliseconds outside of Idle State." : "Idle State was not reached within " + millisecondsTimeout + " milliseconds."; if (failOnError) { Log.Error(message); } else { Log.Warning(message); } return(false); } }