In my program, there is a map editor, after loading the information from the database, I need to generate some custom controls (6000-10000 depending on the map). Unfortunately it locks the user's screen for 10-20 seconds.
How can I do using lazy loading? How can I do without crash and lock screen?
This question is much to broad. But i can give you a number of hints.
First of all i'am pretty sure you don't need so many custom controls. Think about how many input devices the user has, he can't interact with that many controls at the same time. So you can "cheat" about these controls in a couple of different ways. For example, display an image of the control, and switch it if the user starts to interact with it.
Another thing is, you don't need what you don't see. Why create a list of 10000 Elements if only 10 will fit on the screen? There is no reason, thats why there are ways to mitigate that, one is called Virtualization which can be done in a number of ways. You can use UI Virtualization, by defer the loading of the ui components or use data virtualization.
Another thing, in cooperation with data virtualization is to use threads or a background worker to handle the load of that much data. Create your data in batches to give the UI Thread time to handle the windows messages.
Look into Binding or doing the work in a Background thread?
If they are in a ListView, look into VirtualMode:
http://msdn.microsoft.com/en-us/library/system.windows.forms.listview.virtualmode.aspx
What are you loading these controls into? Are you doing it in the UI thread?
Use TPL (Task Parallel Library) to do the DB tasks on a separate thread... it looks like this:
Task.Factory.StartNew(() => MyLongRunningMethod));
Check out this great article over on CodeProject for more information...
EDIT: As noted below the original answer implied that somehow controls can be generated on a separate thread but in reality as a part of the visual tree and therefore the UI, controls must be generated on the UI thread so that was not a valid suggestion...
EDIT: Don't see how it would be possible to fit 10000 custom controls on a signle screen so there must be a way to use some type of virtualization schema where only visible controls would get generated and the rest of the controls would get generated on demand...
Related
I am just wondering if anybody knows anything about the speed of the WinsForms panel control relative to the number of controls placed in it.
I have panels that I need to populate with hundreds of controls and it seems to slow down exponentially. I have tried making the panel invisible when populating it and this doesn't seem to help.
I am asking for two reasons:
To determine if this slow down is the result of the panel control or
a quite complicated (for me) bit of code that is handling the panel
and adding the items to it.
If it is the result of the panel, then I would like to determine if there
is anything I can do about it. I am quite a ways into the project
and the project depends upon panels that contain these controls.
Thanks for your time.
My level of expertise is fairly amateur BTW.
You have not shown your code to load the panel. Moreover you need to add more information in your problem about the controls and loading process. With general assumptions, to speed up you can do :-
Lazy load. User will not interact with hundreds of control at a given time. So, load the controls on demand.
Populate the controls in background thread, and make them ready just before they are required to be shown.
Load them based on the priority of the user interaction.
I have an openGL rendering engine coded in unmanaged C++, and I want to embed this in a WPF application. After a little research, I managed to do it by using the handle of a windows forms panel in a windowsformshost, as explained here (2nd solution):
http://www.codeproject.com/Articles/127141/Unmanaged-C-OpenGL-Drawing-and-C-WinForms-WPF-inte/?display=Mobile
So far good. The problem is, I need the render to be real time, and when some UI operation takes too long (like populating a property grid), the render flickers.
Then I guess I need to do the rendering in a separate thread. I tried to use this approach:
http://blogs.msdn.com/b/dwayneneed/archive/2007/04/26/multithreaded-ui-hostvisual.aspx
But it does not work because it seems i cannot place a windowsformshost inside a HostVisual (http://social.msdn.microsoft.com/Forums/en-AU/wpf/thread/124cc95c-a9c6-4aca-a5fc-4f959ea715c3)
So, any idea how can I do this?
If you use double-buffering then it should never flicker. See the section "How to Avoid Flickering?" in the first article you linked to. You can also try inserting Application.DoEvents() calls inside code that takes a long time to execute. Just some suggestions as an alternative to the added complexity of using a threaded solution.
EDIT: just realized WPF does not support DoEvents(), but there are alternatives: http://nmarian.blogspot.com/2007/09/doevents-in-wpf.html
I have a WPF application that renders input forms based on form-configurations saved in a database.
The forms have many controls (100+) and most of these controls are derived from a TextBox-control. On some machines (fast Hardware, Win7 32Bit, also some elder, Windows XP 32Bit), after entering data to a lot of these forms, input performance goes down. Every keystroke gets a delay of some milliseconds and the only solution to resolve this is to close the application and restart it.
My derived control overrides the metadata of the DefaultStyleKeyProperty to set a custom template.
I'm currently reasearching the app in SciTech memory profiler, but maybe someone has already experienced a similar problem with derived TextBoxes and can give me a hint and spare me some more hours/days investigating the problem?
Update
Look also here
It sounds like you may have something stopping the controls on the "used forms" being GCed.
Firstly opening and use as many forms as possible looking at the windows task manager to see if you memory usage is going up – if it is not there is no point looking for memory leeks
Check you are removing all events handlers you forms/controls have put on any long lived objects.
Check that any objects you databind to implement INotifyPropertyChanged, see KB938416
I have in the past had good results using the Red Gate memory profiler.
You don’t need to have controls created that the user can’t see, 100+ controls will have a cost.
Can you use something list a list control in virtual mode, so your TextBox controls are only created when visible.
I have a UI with some controls, then in the middle I have 6 overlapping grids. I am using these grids as 'pages' and as the user navigates through the 'pages' I cycle through using Visible.Hidden and Visible.Visible to show the correct 'page'.
I noticed while developing as I was adding more grids the application started to slow down (a lot). It wasn't really a problem until I added 6 more images to the last page. Since, the application is very slow even on my (faster than average) PC.
Do you have any advice on how I can still achieve the same look and feel but use a more efficient method?
Thanks in advance.
All in all it's not a good idea to have a bunch of overlapping controls like you have, because as you noticed, there are performance problems. You want to minimize the number of controls which are present in your application at any one time.
If you have a limited number of pages, use TabControl.
If you have a large or dynamic number of pages, consider Frames and Pages.
A third option is to have a hosting "shell" control with a ContentPresenter. Then whenever you want to navigate to a different page, just set the control's Content to a new instance of your page view.
Your views are separate from your data models, right? If not, consider using the MVVM pattern. This will allow you to have persistent data regardless of which view is showing (e.g. dynamically creating and destroying views won't mess up your data).
I suggest that you use the WPF Frame and Page classes instead of your current architecture. As with any presentation framework, performance degrades as you add more controls to your scene graph.
TabControl with a custom template?
We are looking at creating a WPF UI that runs across multiple AppDomains. One of the app domains would run the application while the remaining AppDomains would host a series of user controls and logic. The idea, of course, is to sandbox these User Controls and the logic away from the main application.
Here is an example of doing this using MAF/System.AddIn. What are some of the experiences other have had with this? How does this solution handle RoutedEvents/Commands that might occur inside one user control and do these get properly serialized across AppDomains? What about WPF resources? Can they be accessed across AppDomains seamlessly?
Old question, but nonetheless: You will need to have multiple UI threads - one per AppDomain. Create them like this:
var thread = new Thread(() =>
{
var app = new Application();
app.Run();
});
thread.Name = AppDomain.CurrentDomain.FriendlyName;
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
The biggest challenge is then that you cannot send FrameworkElements between AppDomains (they are not MarshalByRefObject), but you can use the FrameworkElementAdapters.ViewToContractAdapter() and ContractAdapterToView() methods to work around this limitation. See the FrameworkElementAdapters MSDN page for more details.
Then, once you have this in place, the biggest problem IMHO is that you cannot lay anything on top of the FrameworkElement from the "remote" domain (the classical "airspace problem"). See this thread for more info about this.
I answered a simular question here and edited it for WPF also, you can use an intersting property of how the compisition engine operate's to tail-coat a dispatcher Pump, into one of the rendering contexts. It's a really light weight option.
Also, I'm guessing you know about the enterprise library and unity?
There is a WPF application block so using that pattern is not too painful ;) But don't they say, no pain no gain?
There's also CAB (Composite UI Application Block), ties into unity. The WPF SDK folks have crafted a Silverlight & WPF platform. (a.k.a Prism).
Oh right, also, you asked about Resources? I prefer to load reasources manually in the Application class. One thing I've realized, say you have a ResourceDictionary in a sub-folder and you are loading up MergedDictionaries in that ResourceDictionary. So, if in your Application class, you load "my-res-dir/MergedDictionaryLoader.xaml" (by code or xaml), ALL FUTURE LOADS OF MERGEDDICTIONARIES ARE LOADED FROM "my-res-dir".
Sort of insane if you ask me, I would think that as the process current directory has not changed, you should specify "my-res-dir/foo.xaml" for all your additional directories. However this is not the case (I do not believe this is documented anywhere at least very well and should be considered a bug imho).
So remember, WPF resource dictionary loading is going to be based off of the directory from which the current XAML is in. So you specify Source="foo.xaml" from within your "my-res-dir/MergedDictionaryLoader.xaml". I've even played with the URI pack / absolute syntax, however I've never found that too be much more intuative.