Why do UI Controls in WPF have Thread Affinity?

The short description per MSDN is

WPF’s threading model was kept in sync with the existing User32
threading model of single threaded execution with thread affinity. The
primary reason for this was interoperability – systems like OLE 2.0,
the clipboard, and Internet Explorer all require single thread
affinity (STA) execution

The longer description is this:

Most objects in WPF derive from DispatcherObject, which provides the
basic constructs for dealing with concurrency and threading. WPF is
based on a messaging system implemented by the dispatcher. This works
much like the familiar Win32 message pump; in fact, the WPF dispatcher
uses User32 messages for performing cross thread calls.

There are really two core concepts to understand when discussing
concurrency in WPF – the dispatcher and thread affinity.

During the design phase of WPF, the goal was to move to a single
thread of execution, but a non-thread “affinitized” model. Thread
affinity happens when a component uses the identity of the executing
thread to store some type of state. The most common form of this is to
use the thread local store (TLS) to store state. Thread affinity
requires that each logical thread of execution be owned by only one
physical thread in the operating system, which can become memory
intensive. In the end, WPF’s threading model was kept in sync with the
existing User32 threading model of single threaded execution with
thread affinity. The primary reason for this was interoperability –
systems like OLE 2.0, the clipboard, and Internet Explorer all require
single thread affinity (STA) execution.

Given that you have objects with STA threading, you need a way to
communicate between threads, and validate that you are on the correct
thread. Herein lies the role of the dispatcher. The dispatcher is a
basic message dispatching system, with multiple prioritized queues.
Examples of messages include raw input notifications (mouse moved),
framework functions (layout), or user commands (execute this method).
By deriving from DispatcherObject, you create a CLR object that has
STA behavior, and will be given a pointer to a dispatcher at creation
time.

You can read the full article here

Personally I prefer WPF’s single-threaded model over having to use locking and thread synchronization techniques. The Dispatcher can be used to pass messages to the main UI thread at different priority levels, which takes care of the majority of small background processes, and if you need any heavy processing then you can still create your own background thread for that.

Leave a Comment