I am trying to implement a system in WPF that plays two synchronized videos on two screens. I thought that if I bundled the two corresponding MediaTimelines into a single ParallelTimeline and control the timelines from the clock controller of the ParallelTimeline the clocks of the media timelines would be driven from the same clock and thus play in sync. Only that is not the case, there is a huge delay between both. Is there some way of doing this?
Thanks
If your two MediaTimelines are in the same storyboard (and it sounds like they are), you should be able to keep the elements in sync by changing the ParallelTimeline.SlipBehavior to SlipBehavior.Slip. This behavior will "hold back" the progression of the timelines if a media element in the storyboard runs into buffering or loading delays.
You can get more details about this behavior here:
http://msdn.microsoft.com/en-us/library/cc304465.aspx
Related
I have a WPF application that needs to do some processing of many small tasks.
These small tasks are all generated at the same time and added to the Dispatcher Queue with a priority of Normal. At the same time a busy indicator is being displayed. The result is that the busy indicator actually freezes despite the work being broken into tasks.
I tried changing the priority of these tasks to be Background to see if that fixed it, but still the busy indicator froze.
I subscribed to the Dispatcher.Hooks.OperationStarted event to see if any render jobs occurred while my tasks were processing but they didn't.
Any ideas what is going on?
Some technical details:
The tasks are actually just messages coming from an Observable sequence, and they are "queued" into the dispatcher by a call to ReactiveUI's ObserveOn(RxApp.MainThreadScheduler) which should be equivalent to ObserveOn(DispatcherScheduler). The work portion of each of these tasks is the code that is subscribing through the ObserveOn call e.g.
IObservable<TaskMessage> incomingTasks;
incomingTasks.ObserveOn(RxApp.MainThreadScheduler).Subscribe(SomeMethodWhichDoesWork);
in this example, incomingTasks would produce maybe 3000+ messages in short succession, the ObserveOn pushes each call to SomeMethodWhichDoesWork onto the Dispatcher queue so that it will be processed later
The basic problem
The reason you are seeing the busy indicator stall is because your SomeMethodWhichDoesWork is taking too long. While it is running, it prevents any other work from occuring on the Dispatcher.
Input and Render priority operations generated to handle animations are lower than Normal, but higher priority than Background operations. However, operations on the Dispatcher are not interrupted by the enqueing of higher priority operations. So a Render operation will have to wait for a running operation, even if it is a Background operation.
Caveat regarding observing on the DispatcherScheduler
ObserveOn(DispatcherScheduler) will push everything through at Normal priority by default. More recent versions of Rx have on overload that allows you to specify a priority.
One point to highlight that's often missed is that items will be queued onto the Dispatcher by the DispatcherScheduler as soon as they arrive NOT one after the other.
So if your 3000 items all turn up fairly close together, you will have 3000 operations at Normal priority backed up on the Dispatcher blocking everything of the same or lower priority until they are done - including Render operations. This is almost certainly what you were seeing - and that means you might still see problems even if you do all but the UI update work on a background thread depending on how heavy your UI updates are.
In addition to this, you should check you aren't running the whole subscription on the UI thread - as Lee says. I usually write my code so that I Subscribe on a background thread rather than use SubscribeOn, although this is perfectly fine too.
Recommendations
Whatever you do, do as much work as possible on a background thread. That point has been done to death on StackOverflow, and elsewhere. Here are some good resources covering this:
MSDN Entry on WPF Threading Model
MSDN Magazine "Build More Responsive Apps With The Dispatcher", by Shaun Wildermuth
If you want to keep the UI responsive in the face of lots of small updates you can either:
Schedule items at a lower priority, which is nice and easy - but not so good if you need a certain priority
Store updates in your own queue and enqueue them and have each operation you run Invoke the next item from your queue as it's last step.
The bigger picture
It's worth stepping back a bit and looking at the bigger picture as well.
If you separately dump 3000 items into the UI in succession, what's that going to do for the user? At best they are going to be running a monitor with a refresh rate of 100Hz, probably lower. I find that frame rates of 10 per second are more than adequate for most purposes.
Not only that, human beings supposedly can't handle more than 5-9 bits of information in one go - so you might find better ways of aggregating and displaying information than updating so many things at once. For example, make use of master/detail views rather than showing everything on screen at once etc. etc.
Another option is to review how much work your UI update is causing. Some controls (I'm looking at you XamDataGrid) can have very lengthy measure/arrange layout operations. Can you simplify your animations? Use a simpler Visual tree? Think about the popular busy spinner that looks like circling dots - but really it's just changing their color. A great effect that is fairly cheap to achieve. It's worth profiling your application to see where time is going.
I would think about the overrall approach front-to-back as well. If you are reasonably certain you are going to get that many items to update at once, why not buffer them up and manage them in chunks? That would might have advantages all the way back to the source - which perhaps is on a server somewhere? In any case, Rx has some nice operators, like Buffer that can turn a stream of individual items into a larger lists - and it has overloads that can buffer by time and size together.
Have you tried using .SubscribeOn(TaskPoolScheduler.TaskPool) to subscribe on a different thread?
#Pedro Pombeiro has the right answer.
The reason you are seeing the freezes on the UI is that you are queueing the work on the Dispatcher. This means the work will be done on the UI thread. You can think of the Dispatcher as a message pump that is constant draining messages from each of its queues (which you can think of each of the priorities [SystemIdle, ApplicationIdle, ContextIdle, Background, Input, Loaded, Render, DataBind, Normal, Send])
Putting you work onto a different priority queue, does not make it run concurrently, just asynchronously.
To run your work on another thread using Rx, then use SubscribeOn as above. Remember to then schedule any updates to the UI back on to the Dispatcher with ObserveOn.
Can someone please tell me how the processing in Silverlight processes between the UI Thread and the other "worker" threads.
I have a scenario where I have to update several hundred complex UI objects in the view via a viewmodel. Each item is backed by its own viewmodel.
If each viewmodel had a property, for example, called IsSelected, which changed a background color through behaviours, how should I go about making changes to minimal UI Thread blocking?
If I update my (several hundred) viewmodels, it blocks the UI thread for around 4 seconds. How can I determine what's doing the blocking? Are there more efficient ways to update?
Thanks
There are definitely more efficient ways than doing it in one go.
A non-Silverlight specific solution would be to space these updates a few milliseconds apart with DispatcherTimer delayed calls, so the thread has some "breathing space" to carry on with the execution path.
But you should also give some thought to your architecture, if you're dealing with hundreds of VMs it might worth using lazy loading and updating your screen sequentially, in order of importance for your audience.
See this answer too for more explanation: https://stackoverflow.com/a/1710868/21217
In case a screen of a WPF application contains lots of primitive controls, its rendering becomes sluggish. What are the recommended ways to improve the responsiveness of a WPF application in such a case, apart from adding fewer controls and using more powerful videocard?
Is there a way to somehow use offscreen buffering or something like that?
Our team was faced with problems of rendering performance. In our case we have about 400 transport units and we should render chart of every unit with a lot of details (text labels, special marks, different geometries etc.).
In first our implementations we splitted each chart into primitives and composed whole unit's chart via Binding. It was very sad expirience. UI reaction was extremely slow.
So we decided to create one UI element per each unit, and render chart with DrawingContext. Although this was much better in performance aspect, we spent about one month improving rendering.
Some advices:
Cache everything. Brushes, Colors, Geometries, Formatted Texts, Glyphs. (For example we have two classes: RenderTools and TextCache. Rendering process of each unit addresses to shared instance of both classes. So if two charts have the same text, its preparation is executed just once.)
Freeze Freezable, if you are planning to use it for a long time. Especially geometries. Complex unfreezed geometries execute HitTest extremely slow.
Choose the fastest ways of rendering of each primitive. For example, there is about 6 ways of text rendering, but the fastest is DrawingContext.DrawGlyphs.
Use profiler to discover hot spots. For example, in our project we had geometries cache and rendered appropriate of them on demand. It seemed to be, that no improvements are possible. But one day we thought what if we will render geometries one time and cache ready visuals? In our case such approach happened acceptable. Our unit's chart has just several states. When data of chart is changed, we rebuild DrawingVisual for each state and put them into cache.
Of course, this way needs some investments, it's dull and boring work, but result is awesome.
By the way: when we turned on WPF caching option (you could find link in answers), our app hung up.
I've had the same perf issue with a heavily customized datagrid since one year, and My conclusion is:
there is basically nothing you can do
on your side (without affecting your
app, i.e.: having fewer controls or
using only default styles)
The link mentioned by Jens is great but useless in your case.
The "Optimizing WPF Application Performance" link provided by NVM is almost equally useless in my experience: it just appeals to common sense and I am confident you won't learn anything extraordinary either reading. Except one thing maybe: I must say this link taught me to put as much as I can in my app's resources. Because WPF does not reinstanciate anything you put in resource, it simply reuses the same resource over and over. So put as much as you can in there (styles, brushes, templates, fonts...)
all in all, there is simply no way to make things go faster in WPF just by checking an option or turning off an other. You can just pray MS rework their rendering layer in the near future to optimize it and in the meantime, try to reduce your need for effects, customized controls and so on...
Have a look at the new (.NET 4.0) caching option. (See here.)
I have met a similar problem and want to share my thoughts and founds. The original problem is caused by a virtualized list box that displays about 25 complex controls (a grid with a text block and a few buttons inside displaying some paths )
To research the issue I used the VisualStudio Application Timeline that allows to how much time it takes to render each control and PerfView to find out what actually WPF is doing to render each control.
By default it took about 12ms to render each item. It is rather long if you need to update the list dynamically.
It is difficult to use PerfView to analyse what heppens inside since WPF renders item in the parent-child hierarchy, but I got the common understanding about internall processes.
WPF does following to render each item in the list:
Parse template using XAML reader. As far as I can see the XAML parsing is the biggest issue.
Apply styles
Apply bindings
It does not take a lot of time to apply styles and bindings.
I did following to improve performance:
Each button has its own template and it takes a lot of time to render it. I replaced Buttons with Borders. It takes about 4-5ms to render each item after that.
Move all element settings to styles. About 3ms.
Create a custom item control with a single grid in the template. I create all child elements in code and apply styles using TryFindResources method. About 2ms in the result.
After all these changes, performance looks fine but still most time is spent on loding the ListControl.Item template and the custom control template.
4. The last step: replace a ListControl with Canvas and Scrollbar controls. Now all items are created at runtime and position is calculated manually using the MeasureOverride and ArrangeOverride methods. Now it takes <1ms to render each item from which 0.5ms is spent on TextBlock rendering.
I still use styles and bindings since they do not affect performance a lot when data is changed. You can imagine that this is not a WPF solution. But I fave a few similar lists in the application and it is possible not to use templates at all.
I have a a bunch of WPF UserControls that internally trigger some animations upon user interactions. All animations have repeatbehavior = "true" and all animations have the same duration. Now I would like synchronize all those animations on one timeline so they are fading in and out in sync. No matter when the user triggerd the animations. For example if the animations all last 3 secs and the user triggers the 2nd animation 1.5 secs after the first, I still want the animations reach their maximum at the same time.
Maybe I can define a global time line in a global resource dictionary that all animations that are defined somewhere in the UserControls can use? Preferably XAML only.
Simply add all of your animations to a single TimelineCollection. Then add that TimelineCollection to your Storyboard.Children. Then they will all fire simultaneously.
XAML: impossible (as far as I know)
code: CompositionTarget.Rendering
Maybe my post can help you http://translate.google.it/translate?js=n&prev=_t&hl=it&ie=UTF-8&layout=2&eotf=1&sl=it&tl=en&u=http%3A%2F%2Fblogs.ugidotnet.org%2Fleonardo%2Farchive%2F2011%2F01%2F08%2Fsincronizziamo-le-animazioni-con-wpf.aspx&act=url (is in Italian and link is of Google Translate)
I'm trying to learn WPF animations and am currently confused by quite a few things:
I used tools like processing, where you have a simple method which is called n times per minute, where n is the frame rate.
The way to do animations in WPF is to modify a property. If i use for example DoubleAnimation then a double is increased as the animation proceeds. But this is not exactly what I want. I want that in every cycle some properties are increased, some are modified by random and some are modified by user interaction. How can I do this in WPF?
What is also confusing me is the fact that WPF supports multiple animations at the same time. How does this work? Is there a thread for every animation or just one for all animations.
I used gdi with c# some time ago. I even could use multiple threads for drawing; As far as I remember I just had to insert all the drawing commands in some queue and then windows took care of them.. I have no idea how this is handled with WPF.
On a basic level, WPF animations are just the same as any other kind of animation: internally a timer ticks and some properties are modified which lead to a different picture when drawn to the screen.
WPF does all the leg work for you to be able to specify animations relative to wall-clock time, like "move that box at 3mm per second to the left". For more complex scenarios you might want to code up your own Animation, see the Custom Animation Overview article on the MSDN.
Regarding threading, WPF works the same as GDI: There is one Thread that handles all the interaction with the WPF model and you can only talk to WPF Controls if you're running on this thread. You can use the Dispatcher to "send" code to this thread if you are free threading. Actual drawing to DirectX is done in a separate thread, but that is of no concern to casual users of the API.
You can run several animations at the same time by putting them into a StoryBoard.
You can use the animation's BeginTime to get one animation to start after another.
You can use the key frames version (DoubleAnimationUsingKeyFrames) or the path version (DoubleAnimationUsingPath) to create complex non-linear animations.