Your problem is inherently serial -- you must complete an update of the simulation before you can render it. Offloading the simulation to a different thread simply means the main UI thread does nothing while the simulation thread ticks (which means it is blocked). I strongly recommend
The commonly held "best practice" for concurrency is not tryingnot to take a concurrent approach forput your specific problem, it's not the ideal solutionrendering on one thread and it will gain you nothing but complexity for basically no payoff.
That saidyour simulation on another, as you can alleviate the issue by isolating the data consumed by either threadare proposing. Split the render data out of the simulation data entirely (this is good practiceI strongly recommend against that approach, in general)fact. The main thread can constant render from the render datatwo operations are naturally serially related, and the simulation threadwhile they can constantly update its databe brute forced, it's not optimal and it does not scale.
There will be someA better approach is to make parts of this data that are inherently sharedthe update or rendering concurrent, but leave updating and in any case you'll need to update the render thread's data with the results of the simulation datarendering themselves always serial. You can do this by locking and copyingSo for example, if you must, but that's crude (and a lock is essentially a block anyhow). You could also usehave a concurrentnatural boundary in your simulation (locklessfor example, if houses never affect each other in your simulation) queue to enqueue messages containing state updates toyou can shove all the rendererhouses into buckets of N houses, which it can apply prior to starting a new render pass. Note that this tends to imply that you are renderingand spin up a frame (or several) behind the actual statebunch of threads that each process one bucket, and let those threads join before the simulationupdate step is complete. This scales much better and can be tedious to debugis a much better fit for concurrent design.
You're overthinkingover-thinking the rest of the issue:
Dependency injection is a red herring here: all dependency injection really means is that you pass ("inject") the dependencies of an interface to instances of that interface, typically during construction.
That means if you have a class that models a House, which needs to know things about the City that it is in, then the House constructor might look like:
public House( City containingCity ) {
m_city = containingCity; // Store in a member variable for later access
...
}
Nothing special.
Using a singleton is unnecessary (you often see it done in some of the insanely complex, over-engineered "DI frameworks" like Caliburn that are designed for "enterprise" GUI applications -- this does not make it a good solution). In fact, introducing singletons is often the antithesis of good dependency management. They also can cause serious problems with multithreaded code because they cannot usually be made thread-safe without locks -- the more locks you must acquire, the worse your problem was suited for handling in a parallel nature.