RootElement Measure and Arrange

Sep 29, 2009 at 4:17 PM

i'm trying to get a control to run on a second thread. but i'm having a few issues. the first is that i'm not sure how to get the available size to pass into the measure call that's in the RootVisual property of the VisualTargetPresentationSource class. maybe it's a problem in my actual control...

another issue i'm having is with is when i have an animation using HLSL effects it doesn't want to play with me at all B(

Coordinator
Sep 29, 2009 at 5:12 PM

Layout across the threads is difficult, because the threads are independent.  So, for example, the controls on the worker thread could decide to change size (their content got larger, or the string got longer, or something).  You could asynchronously pass that to the UI thread to use as the HostVisual's size.  But if layout on the UI thread further constrains the layout size, then you would have to asynchronously pass the constraint back to the worker thread... who would re-run layout and might end up with a different size again...

The simplest technique is probably more static.  Decide on a fixed size for the worker thread's content and use that when measuring the root.

I'm not aware of any issues with shader effects... Can you post a repro?

Jan 22, 2010 at 2:52 PM
Edited Jan 22, 2010 at 5:32 PM

Is it a bug or a feature, in case when UI thread that renders content of an HostVisual class object is blocked, the entire parent window becomes blocked as well?

i.e. I added private FrameworkElement _player to class Window1 which is for demonstration purposes always assigned inside MediaWorkerThread method:

visualTargetPS.RootVisual = _player = CreateMediaElement();

then if I change your provided sample OnLoaded event:

        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            Player1.Child = CreateMediaElementOnWorkerThread();
            Player2.Child = CreateMediaElementOnWorkerThread();
            Player3.Child = CreateMediaElementOnWorkerThread();

            _player.Dispatcher.BeginInvoke(
                (ThreadStart)delegate()
                {
                  Thread.Sleep(10000);
                },
                System.Windows.Threading.DispatcherPriority.Normal,
null
            );
        }

entire parent window (main UI thread I suppose) will be blocked after loading for 10 secs?!

 

Coordinator
Jan 22, 2010 at 5:49 PM
This is the consequence of the single-threaded message-pumping design that Win32 is built on. Almost all interaction with windows in Win32 is done through messages. Every window is owned by a thread, and that window is only responsive if the owner thread is pumping messages. WPF is no different.
Jan 23, 2010 at 2:16 PM
Edited Jan 23, 2010 at 4:50 PM

I understand that, but I did not know that it is normal behavior when the worker thread which owns the element tree that is being rendered into its own VisualTarget blocks - the owner thread of the window containing the HostVisual parent object will be blocked as well - I supposed that in that case visual contents of HostVisual objects on parent window will not be updated but the window will remain responsive.

So by using this approach via VisualTarget/HostVisual objects we can not really achieve asynchronous rendering of heavyweight WPF visuals (i.e. complex composite drawings, large bitmaps ...) without blocking?