Bing and decide.
Hey Jer,
I Dwayned* it in-house and this is what I got back..
The WPF dispatcher is not just a queue of delegates. It is deeply integrated with the Win32 message pump design. For instance, delegates queued at “foreground” priorities are interleaved with other posted win32 messages. Further, we guarantee that delegates queued at “background” priorities will only be dispatched after all other posted/sent/input Win32 messages are dispatched. We don’t provide any way to cheat. Because cheating would break the contract for other consumers of the Dispatcher API that depend on that contract.
The DShow APIs you are calling are evidently running their own nested message pumps. This means that they call GetMessage() and DispatchMessage(). If they dispatch our ProcessQueue message, we will process the next delegate in the queue in priority order. If we didn’t we would be breaking the contract. Imagine code that posts a work item at Normal priority. This item, by definition, must be executed before input is processed. But the nested message pump will very likely pump input messages. So if we don’t respond when it is our turn, then we break the contract.
Nested message pumps cause reentrancy. WPF is designed to continue working even if an app causes reenentracy – such as your app is causing by calling into DShow. This is important, because we need layout, rendering, animations, etc, etc to continue working. We do offer a mode, as you have noted, where we will throw an exception if there is any reentrancy (this is a defensive mode for code paths that cannot survive reentrancy). But we do not offer a mode where we simply suspend the dispatcher during reentrancy.
Now, of course, you can fix for your scenario in several ways. For example, you could keep your own list of async operations. Then you could post one work item to do the next thing in your list. You could even ensure that you won’t do anything on your list until you have finished the previous item (refuse reentrancy). Of course, I’m not sure how much value the WPF dispatcher is then providing for you…
*Dwayne Need is a Dev Manager in WPF. He is not as handsome as dr. wpf, but he knows his stuff equally well and he owns the dispatcher.
Great explanation!
Thanks Jaime
From: wpf-di...@googlegroups.com [mailto:wpf-di...@googlegroups.com] On Behalf Of Jaime Rodriguez
Sent: giovedì 24 settembre 2009 07:47
To: wpf-di...@googlegroups.com
Subject: [WPF Disciples] Re: Dispatcher and Win32 message pump blues
Hey Jer,
I Dwayned* it in-house and this is what I got back..
The WPF dispatcher is not just a queue of delegates. It is deeply integrated with the Win32 message pump design. For instance, delegates queued at “foreground” priorities are interleaved with other posted win32 messages. Further, we guarantee that delegates queued at “background” priorities will only be dispatched after all other posted/sent/input Win32 messages are dispatched. We don’t provide any way to cheat. Because cheating would break the contract for other consumers of the Dispatcher API that depend on that contract.
The DShow APIs you are calling are evidently running their own nested message pumps. This means that they call GetMessage() and DispatchMessage(). If they dispatch our ProcessQueue message, we will process the next delegate in the queue in priority order. If we didn’t we would be breaking the contract. Imagine code that posts a work item at Normal priority. This item, by definition, must be executed before input is processed. But the nested message pump will very likely pump input messages. So if we don’t respond when it is our turn, then we break the contract.
Nested message pumps cause reentrancy. WPF is designed to continue working even if an app causes reenentracy – such as your app is causing by calling into DShow. This is important, because we need layout, rendering, animations, etc, etc to continue working. We do offer a mode, as you have noted, where we will throw an exception if there is any reentrancy (this is a defensive mode for code paths that cannot survive reentrancy). But we do not offer a mode where we simply suspend the dispatcher during reentrancy.
Now, of course, you can fix for your scenario in several ways. For example, you could keep your own list of async operations. Then you could post one work item to do the next thing in your list. You could even ensure that you won’t do anything on your list until you have finished the previous item (refuse reentrancy). Of course, I’m not sure how much value the WPF dispatcher is then providing for you…
*Dwayne Need is a Dev Manager in WPF. He is not as handsome as dr. wpf, but he knows his stuff equally well and he owns the dispatcher.