The multi-threading (main thread, RenderProcess, LoaderProcess, and UpdaterProcess) is an important element of Open Rails’ design. It enables the operating system to exploit systems with multiple processors.[1]
Let’s outline the roles of the three concurrent subsidiary threads.
Render Process
When RenderProcess is instantiated, its constructor builds a window and instantiates an XNA GraphicsDeviceManager class. As mentioned above, after the constructor returns, RenderProcess.Run is called, which starts the XNA game loop. This will run, synchronized with the refresh rate of the monitor, processing all events associated with the game window, until the game ends.
With the game loop running and the graphics device ready, but before the first frame is displayed, RenderProcess.Initialize will be automatically called. This performs the following:
- Viewer and materials initialization.
- Creates and initializes all renderers (“drawers”) and cameras.
- Loads terrain, scenery, and trains for the starting position of the player train.
- Starts the LoaderProcess thread that will run a game loop responsible for loading “content” (terrain, scenery, trains, etc.).
- Similarly, it starts the UpdaterProcess thread for a multiprocessor system.
- Unpauses Simulator.
Paced at the monitor’s native frame rate, RenderProcess.Draw gets called to actually render all the primitives for the next frame (prepared by UpdaterProcess).
Loader Process
Once LoaderProcess has started, it runs a loop that waits until signaled to start. Then it loads any new graphics content required by the camera position, and it signals when it is done and branches back, ready to do it again.
Updater Process
Let’s assume (temporarily[2]) that our configuration has more than one processor.
UpdaterProcess also runs a loop (UpdaterProcess.UpdateLoop) that is responsible for preparing each frame for rendering. The loop begins with a wait until signaled to start. Then it does the following:
- Keeps track of real time (wall clock) and computes frames-per-second (FPS).
- Calls Viewer.Simulator.Update to update the state of the simulation.
- Handles user inputs that were read in the RenderProcess thread.
- Prepares a frame for display. This involves calling a number of specialized preparers (sky, terrain, scenery, etc.) that queue up “primitives” (e.g., mesh) for rendering. The list of preparers is:
- Camera.PrepareFrame
- SkyDrawer.PrepareFrame
- TerrainDrawer.PrepareFrame
- SceneryDrawer.PrepareFrame
- TrainDrawer.PrepareFrame
- PrecipDrawer.PrepareFrame
- InfoDisplay.PrepareFrame
- Signals RenderProcess that it can proceed to render the frame just prepared.
- Signals UpdaterProcess that it can proceed to load new content.
The behavior of the above three processes must be synchronized. The descriptions above hint at some of that synchronization. The simplified illustration below attempts to illustrate the time-wise coordination of the processes. (Time flows down the page. The time axis is, in no sense, to scale.)

| Previous section: Major Components | Up to: Design Overview | Next section: Open Rails Terrain |
[1] Fire up the Resource Monitor associated with Windows Task Manager when Open Rails runs in windowed mode to watch the multiprocessing fun.
[2] I presume that updating is done in the main thread in the uniprocessor case. However, I really don’t know the details of how this is handled. (More on this as my orientation progresses.)