There are 2 threads ... the main user interface thread .... and the rendering thread .... you may need to look at both to determine the responsiveness of your application ... and decide how to throttle.
Measure FrameRate
You can watch ETW events or handle CompositionTarget.Rendering and count the frames yourself .... it keeps track of the rendering stream ... if it drops frames, then it can tell you that your system is overloaded ... and you can activate the background accordingly mode.
Use a timer to work with a schedule
You can use DispatcherTimer, as @HenkHolterman mentioned, to control the loading of the UI thread, making it work with a priority lower than Normal, for example. Background .... when the timer event is handled / handled in the user interface thread ... you can then release / inform your background worker about the next work item.
But be careful ... if your time interval is too small ... and your system is overloaded ... then you can get a collection of timer messages ... and therefore, when the event handler is called ... you can do too much work ( if you have not saved the record of the last call).
Run delegate in user interface thread
Alternatively, you can simply get a delegate to run in the user interface thread with a specific priority (for example, usually Background).
If you use Dispatcher.BeginInvoke ..., then the job will be queued and will be executed when all jobs with a higher priority are completed. (Asynchronous).
If you use Dispatcher.Invoke ... then your thread will block until all the higher-priority work in the dispatcher calling you is completed, then your delegate will do it.
(your background worker would do this when he has finished his unit of work, and the delegate will then inform your background worker of the next unit of work).
This may be better than DispatchTimer, as you can remove some delay ... i.e. using a timer will have a delay depending on the timer interval.
Then, depending on what you find, you can configure the next block of work.
Monitoring various system performance counters
If you really want to get complex information, you can control various performance counters inside your application, for example. use memory, GC collections, etc ... and dynamically throttle the amount of work you do.
Some Background Dispatcher