I have an application that contains a bunch of sections, each containing data that takes significant time to calculate. There are a few approaches I can see to this:
-
Simple solution 1: Calculate the data in all the sections on application startup. This means application startup will be slow.
-
Simple solution 2: Calculate the data in each section as the user loads it. This means that loading each section will be slow (which is bad, because each section has to do significant rendering calculation already, so they’re already a bit slow.
-
Because performance is critical for this application, neither of these solutions is ideal. So this brings me to a less-simple solution: on app startup, start calculating section data on a background thread. The problem with this solution is that I don’t have a good way of predicting which section the user will load first. So if they load the last section to load on the background thread, they’ll end up waiting longer than if I had just gone with solution 2.
-
So this brings me to solution: on app startup, start calculating section data on a background thread, but when the user loads a section, pause the background thread and start the calculation for the section the user requested. Unless the calculation is already started, in which case you let it finish.
I’m not sure how to implement solution 4. I think the simplest solution is probably to use a priority queue and just up the priority of a task when it’s loaded, but I’m not sure how to implement this in C#. Is this a reasonable approach? What good libraries are there for priority queues in C#?
So we’ll start with an array (or some other data structure if you want) of
Task<Section>objects.You should ensure that the collection is created and actually define the tasks at the very start of your application (not in the background).
Then you can start the background task to actually process the tasks one at a time:
You could use a
Parallel.Forif you want to have several threads working on items.That method uses this helper method:
Then to actually get a finished section (starting it if needed):
If you need a non-blocking version of that (possibly to
awaitit) you can use this: