View Issue Details

IDProjectCategoryView StatusLast Update
0001679NoesisGUIC# SDKpublic2020-06-13 01:51
Reporterdarthmaule2Assigned Tosfernandez 
Status feedbackResolutionopen 
Product Version3.0.0 
Target Version3.0Fixed in Version 
Summary0001679: Request that the Dispatcher optionally take a DispatcherPriority parameter
DescriptionThere's a feature of the WPF dispatcher that I wonder if Noesis could provide for their Dispatcher.

On the WPF Dispatcher, BeginInvoke can optionally take a parameter of type DispatcherPriority. This allows you to specify when the delegate gets executed, so it can be prioritized properly with respect to other things. In particular, you can say whether the delegate should be higher or lower priority than rendering, user input, etc.

If their dispatcher already has this concept of priorities, it would be nice if they exposed a way to specify which priority level the delegate should be executed at. If the Noesis Dispatcher doesn't have the concept of priorities the way that the WPF one does, then no change.




2020-05-05 01:20

manager   ~0006319

Noesis Dispatcher executes all the enqueued operations during window update (after input processing and before window render).
We can add a priority to sort operations in the queue, but they will all be processed just before rendering the window. Is that what you need?


2020-05-05 01:52

reporter   ~0006320

Last edited: 2020-05-05 01:53

View 2 revisions

No, we're not looking to sort the various enqueued operations against each other. We're looking for the ability to sort the various enqueued operations against the dispatcher's internal operations.

In WPF, the priority list is (in part):
- Background
- Input
- Loaded
- Render
- DataBind
- Normal
- Send

So, If I wanted to execute something that needed to happen after window rendering (perhaps because it uses properties that are only set during render, such as ActualWidth), then I can call BeginInvoke with priority Render or below. Something that was enqueued with priority Loaded or below might see several frames rendered before it executes. If I've got something that needs to explicitly happen before the next render, then I can BeginInvoke at priority Normal. If I continue to enqueue operations at a priority higher than Render (e.g., "Normal"), then I can freeze up the UI temporarily, because it's continually busy doing my things instead of rendering.

This all has to do with how the WPF Dispatcher works internally. From what I can tell, it internally does its work using this same priority list. If the Noesis Dispatcher has a similar priority list, we'd like the ability to explicitly enqueue an operation at higher or lower priority, relative to the internal operations that the Noesis Dispatcher is already doing.

I'm not suggesting a radical change to the Noesis Dispatcher. If this concept fits in with the existing way that the Noesis Dispatcher executes its internal operations, then let us specify a priority relative to the internal operations.



2020-05-08 13:54

manager   ~0006334

Hi David,

I exposed DispatcherPriority in Dispatcher invoke functions as a first step towards a correct implementation of dispatcher priorities.
As I said before our dispatcher does not really handle a priority queue, and all queued operations are processed at the same time, just before window gets updated:
 - Process input
 - Process dispatcher queue
 - Update window (Measure, Arrange, OnRender, Loaded)
 - Render window


2020-05-12 22:47

reporter   ~0006354

OK, so the current implementation is that all items queued with BeginInvoke are run after input, but before updating & rendering the window.

If that's the case, can there be a couple different queues, so we can select when something gets run?

Perhaps something like this:
- Process input
- Process dispatcher queue A
- Update window (Measure, Arrange, OnRender, Loaded)
- Process dispatcher queue B
- Render window
- Process dispatcher queue C

Dispatcher.BeginInvoke() could have an overload that takes an enum, where the enum has values along the lines of "AfterInput", "AfterUpdate", "AfterRender". Application writers can specify one of those values to control which queue the invoke delegate is added to. The default overload of BeginInvoke would continue to put items into queue A, as it already does.

This would give us the control over when things get executed that we want, and I don't think it would be a major change to the Dispatcher.


2020-06-13 01:51

reporter   ~0006438

Update: We have a workaround to invoke after a full render cycle has occurred. It's working, and the above proposed change would only be a minimal improvement. (I think I mentioned this on the phone last month.)

Given a delegate to be invoked after the next render cycle, we BeginInvoke a helper delegate that BeginInvokes the actual delegate. Through experimentation, I found that calling BeginInvoke from a delegate that's being run from the dispatcher causes it to be run on the next "Process Dispatcher Queue", rather than the current one. (In other words, a delegate that BeginInvokes itself doesn't force it to stay in "Process Dispatcher Queue" forever. It ends up running on every iteration, but not blocking progress.)

So, right now we're doing BeginInvoke(() => BeginInvoke(actualWork). If we did have the multiple dispatcher queues, we'd end up implementing BeginInvoke(AfterInput, () => BeginInvoke(AfterRender, actualWork), which is only a marginal improvement, only saving the time to run the "Process Input" of the following loop iteration.

Issue History

Date Modified Username Field Change
2020-05-04 19:22 darthmaule2 New Issue
2020-05-04 19:22 darthmaule2 Tag Attached: C#
2020-05-04 22:08 DavidYawCSpeed Description Updated View Revisions
2020-05-05 01:20 sfernandez Assigned To => sfernandez
2020-05-05 01:20 sfernandez Status new => feedback
2020-05-05 01:20 sfernandez Note Added: 0006319
2020-05-05 01:20 sfernandez Target Version => 3.0.0
2020-05-05 01:52 DavidYawCSpeed Note Added: 0006320
2020-05-05 01:53 DavidYawCSpeed Note Edited: 0006320 View Revisions
2020-05-06 16:29 jsantos Target Version 3.0.0 => 3.0
2020-05-08 13:54 sfernandez Note Added: 0006334
2020-05-12 22:47 DavidYawCSpeed Note Added: 0006354
2020-06-13 01:51 DavidYawCSpeed Note Added: 0006438