Wiki Navigation
- Loading...
Threading-Model in the SkinEngine
- There are multiple active threads in the SkinEngine like the render thread, the ScreenManager's asynchronous message queue, the ScreenManager's garbage collector, the input manager's thread, potentially threads of UI model bindings, ...
- Basically, those components follow the general threading guidelines of MP2, with some exceptions
- Screens have a more detailed threading model
Threading-Model of UI elements in screens and theme resources
- Elements in screens and theme resources are potentially accessed by multiple threads:
- Render thread
- Input thread
- Model threads via bindings
- To manage multithreaded access, UI elements pass through four states:
- Available state
- Preparation state
- Running state
- Disposing state
- All those state have different threading models
1) Available state (ElementState Available)
- Single-threaded during loading phase, after that phase Only reader threads allowed
- Screen is not set in elements
- Bindings are not bound but added to a pending bindings collection in their parent UIElement/DependencyObject
- Values in method SetValueInRenderThread are not set
This state is the initial state each UI element is in. All theme resources or other resources used in ResourceDictionary instances remain in this state. Also all resources which are assigned to active/running UI elements as style or template resources (Style, Template, ...) remain in this state until they are disposed.
This state optimizes bindings (they are not activated) and thus, elements in this state are never written, so it is safe to access those theme
resources and style resources with multiple reading threads (DeepCopy).
(Note that there are exceptions to that statement: ResourceWrapper instances are able to force bindings to be bound by setting their EnableBindngs attribute to true.)
2) Preparation state (ElementState Preparing)
- Single-threaded, writing and reading allowed
- Screen is not set in elements
- Bindings are bound, all pending bindings are bound
- Values in method SetValueInRenderThread are set at once
This state is for optimizing performance; elements might be prepared before they are rendered. Here, for example lists are generated and other time consuming tasks are done to prepare an element. When elements are switched to this state, typically the caller is not in a time-critical state;
normally, we switch to this state in the screen preparation phase where we are in the ScreenManager's async message queue thread. But this state is also used when preparing elements from the render thread, so here, we ARE in a time critical thread. The SkinEngine's code is optimized to prepare elements outside of the render thread as often as possible. The important thing is, in this state we optimize setting values in method SetValueInRenderThread in that way that we set the value at once. That can be done because here, we are single-threaded, i.e. the render thread does not yet render the element.
3) Running state (ElementState Running)
- Multi-threaded, only one writer thread, multiple reader threads
- Screen is set in elements
- Bindings are bound and might update values via method SetBindingValue, which delegates to SetValueInRenderThread
- Assign values in method SetValueInRenderThread are added to the screen's animator's pending properties collection, which is processed by the render thread
This is the only state where elements can be used for rendering. Typically, they are allocated in this state.
In this state, only one thread is allowed to write. Normally, this is the render thread. The writer thread must aquire the screen's lock. The render thread aquires that lock during the prepare and render calls and sets all pending values which have been added by calls to method SetValueInRenderThread from other threads. Furthermore, the render thread calls the animator's processing methods.
Reader threads are allowed to read single property values. In very rare situations, it is valid for other threads than the render thread to write
values; in that case, the thread MUST aquire the screen's lock.
4) Disposing state (ElementState Disposing)
- Single-threaded, writing and reading allowed
- Bindings are disposed
- Assign values in method SetValueInRenderThread are discarded
In Disposing state, elements are not rendered any more. The whole element tree is (being) disposed.
This page has no comments.