Open lindexi opened 5 years ago
I prefer to add some APIs to provide the ability to change the _dispatcher
field to null recursively. This helps us to create visuals or controls in a background thread and use it in the main UI thread. This is a great performance improvement.
This would be especially useful for loading images. It's really annoying that you have to load them on the UI thread.
Unfortunately, as far as I understand the implementation, images are using native COM components which are bound to a thread (apartment) and not a dispatcher, so the implementation may not be as easy as it sounds.
@walterlv No, thats just generating an image from XAML, also useful but not what I meant. What I mean is loading an image from data I provide.
In WPF I can calculate the image content off-thread but it is still very costly to load a byte array of content into a WPF image instance, and you are forced to do it on the UI thread because otherwise the image will have the wrong dispatcher. WPF has no auto-throttling so if you happen to construct multiple images in the same layout pass (e.g. a list of thumbnails getting constructed through data binding) you get a huge lag spike when WPF tries to transfer image content into its internal representations.
It would be immensely useful if I could construct bitmap objects on a dedicated Dispatcher thread and later transfer them to the UI thread when they are loaded and ready to render. But that will cause problems because the underlying technology (WIC) is COM and thus bound to a threading apartment.
This is a great idea @lindexi, thanks for opening it! There is a lot to dissect here, and I think we need to make sure that we have a solid understanding of the design and implications of it. Can you clarify a little more on what the exact ask is? You mentioned some API that would null out the dispatcher, do you have an idea of what this API would look like? It almost sounds like you want the ISealable
interface to be exposed publically? Or do you want to be able to null any DependencyObjects
dispatcher?
At the common development, we do not need to share or new a DependencyObjects
. We only need it when we new a DependencyObjects
in other thread.
But I think the Dispatcher
can be inherited like DataContext
that we can create the object in UI thread that works as previous and we can share the DependencyObject
to other thread.
The other way, we can open a static method to set the dispatcher in dependency property recursively. And the static method is in the namespace that known to few.
Sometime, we may write the code cross thread to improve performance. But we are hard to share the dependency property to other thread.
As we know the DependencyObject is inherited from DispatcherObject in WPF. And the WPF use DispatcherObject.CheckAccess to check the calling thread and the creating thread. Some of the dependency property will call the DispatcherObject.DetachFromDispatcher to set their dispatcher to null to share the dependency property to other threads.
But I need to change all of the DependencyObject in a control that I want to share it with other threads. I hope we can use some method like Freeze to freeze some control to share it with other threads. Or we can set the dispatcher in dependency property recursively.