* Update _TerminalCursorPositionChanged to use ThrottledFunc.
* Rename previous ThrottledFunc to ThrottledArgFunc because now
ThrottledFunc is for functions that do not take an argument.
* Update ThrottledFunc and ThrottledArgFunc to accept a CoreDispatcher
on which the function should be called for convenience.
* Don't use coroutines/winrt::fire_and_forget in
ThrottledFunc/ThrottledArgFunc because they are too slow (see PR).
_AdjustCursorPosition went from 17% of samples to 3% in performance
testing.
In addition to the below (original) description, this commit introduces
a ThrottledFunc template that can throttle _any_ function. It applies
that type to muffle updates to the scrollbar.
---
Redo #3531 but without the bug that it caused (#3622) which is why it
was reverted.
I'm sorry if I explain this badly. If you don't understand a part, make
sure to let me know and I will explain it better.
### Explanation
How it worked before: `Terminal` signals that viewport changed ->
`TermControl::_TerminalScrollPositionChanged` gets called on the
terminal thread -> it dispatches work for later to be ran the UI thread
to updates the scrollbar's values
Why it's bad:
* If we have many viewport changes, it will create a long stack of
operations to run. Instead, we should just update the scroll bar with
the most recent information that we know.
* Imagine if the rate that the work gets pushed on the UI thread is
greater than the rate that it can handle: it might freeze?
* No need to be real time, we can wait just a little bit (8ms) to
accumulate viewport changes before we actually change the scroll bar's
value because it appears to be expensive (see perf below).
Now: `Terminal` signals that viewport changed ->
`TermControl::_TerminalScrollPositionChanged` gets called on the
terminal thread -> it tells the `ScrollBarUpdater` about a new update ->
the `ScrollBarUpdater` only runs one job (I don't know if that's the
right term) on the UI thread at a time. If a job is already running but
hasn't updated the scroll bar yet, it changes the setting in the already
existing job to update the scroll bar with the new values. A job "waits"
some time before doing the update to throttle updates because we don't
need real time scroll bar updates. -> eventually, it updates the scroll
bar If the user scrolls when a scroll bar update is pending, we keep the
scroll bar's Maximum and Minimum but let the user choose its new Value
with the `CancelPendingValueChange` method.
### Note
Also I changed a little bit the code from the Terminal to notify the
TermControl less often when possible.
I tried to scroll with the scroll bar, with the mouse wheel. I tried to
scroll while content is being outputted.
I tried to reproduce the crash from #2248 without success (good).
Co-authored-by: Leonard Hecker <leonard@hecker.io>
Closes#3622