By Edhy Rijo - 4/11/2008
Hi,I am working on my first SF application, and testing outside the VS debugger, I noticed some slowness on the winforms when loading. I prepared a small sample video so you can see what I mean. http://www.progytech.com/videos/SF_Sample.html Please let me know if there is any settings I need to do in order to adjust this unwanted effect. The computer where this is being test is running Vista 64bits with 8gb ram.
|
By Edhy Rijo - 4/11/2008
I forgot to mention that I am loading the forms using Trent's technique in this message:http://forum.strataframe.net/FindPost5199.aspx
|
By Trent L. Taylor - 4/11/2008
This question is always like asking, "How long is a string?" There are hundreds of little things that you can do to drastically improve performance. Sometimes this requires that you get a code analyzer to see where all of your trouble spots are, but I can already tell from your video that you are fighting two things:- You are putting all of your load logic in the New or Load of form without threading anything. When you place all of your load logic in the New or Load, you are obviously going to slow instantiation. There are many different things that you can do here. First, you can use the SF ThreadManager control to help you in thread management if you are not adept at creating and managing threads. You can perform the loading of the data from the server on the thread while the UI is on the main thread, thus impoving the rendering and instantiation. You also want to optimize your queries and make as few trips to the server as possible when loading. For example, if you are loading data into more than one business object, you can make a single trip to the server by using the FillMultipleDataTables method (version 1.6.5 or later, you can refer to the docs and samples on this new method).
- Reduce the number of gradients and transparent requirements of the dialog. You can have a very attractive themed interface by using a themed panel that has the RenderAsSolidBackground property set to True. Then the ThemedGroupBoxes TransParent property to False, FillBody to False, ThemeSupport to ColorsOnly, and the HeaderStyle to WindowsStyle (or whichever style you prefer). When you then place the labels and textboxes within the group box it will render more quickly.
I could talk for hours on this very topic (and actually will in the July class) Past this, it will be more of a consultation type of thing for me to look at your specific application and tell you how to speed things up...but there are a lot of little things that add up to a lot. Recently I was talking with someone who had a process that was taking 45 minutes....after talking he got this down to less than 30 seconds. So many times it is just a matter of taking a different approach to improve performance. But as we all know, this is nothing new to WinForms development! Give me a Cray and I can probably find a way to slow it down
|
By Edhy Rijo - 4/12/2008
Hi Trent,I will try all your suggestions but, all these forms and very simple lookup maintenance forms with less than 30 records each, here is the code in the form's class: Public Class frmProducer Private Sub ProducerBO1_ParentFormLoading() Handles ProducerBO1.ParentFormLoading Me.ProducerBO1.FillAllRecords() End SubEnd ClassHere is the code in the ProducerBO.vb: Public Sub FillAllRecords() Me.FillDataTable("SELECT * FROM Producer")End Sub Protected Overrides Function GetCustomBindablePropertyDescriptors() As FieldPropertyDescriptor() ' Create and return a new array of FieldPropertyDescriptor objects that contains ' the ReflectionPropertyDescriptor for the Custom Fields. Return New FieldPropertyDescriptor() _ { New ReflectionPropertyDescriptor("ProducerFullAddress", GetType(ProducerBO))}End Function''' <summary>''' This property will return the Producer Full Address''' </summary>''' <value></value>''' <returns></returns>''' <remarks></remarks><Browsable( False), _BusinessFieldDisplayInEditor(), _ Description( "Producer Full Address"), _DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _ Public ReadOnly Property [ProducerFullAddress]() As System.String Get ' Format the Full Address string Dim cFullAddress As StringBuilder = New StringBuilder cFullAddress.AppendLine( Me.ProducerName) cFullAddress.Append( Me.Street) cFullAddress.Append( " " & Me.City) cFullAddress.Append( " " & Me.State) cFullAddress.AppendLine( " " & Me.Zip) cFullAddress.AppendLine( " Phone " & Me.Phone & " Fax " & Me.Fax) cFullAddress.Append( Me.EmailAddress) Return cFullAddress.ToString End GetEnd Property As you can see this is a very basic simple stuff, I used the same coding in all these maintenance forms and they all show the slow rendering when running from the .EXE outisde the VS IDE. Once I made the changes you suggested and re-test, will let you know if there is any improvement.
|
By Trent L. Taylor - 4/12/2008
OK...I see a few things that I would probably tweak a little, but you kindof missed my point. There is more going on than what you just showed me in that code. Let me put it to you in another way, I have a form that I have been working on recently that pulls from a very large data set from more than 10 different tables...there are over 200 controls on these pages once all added up. I have the form popping up with virtually no lag or delay...using the SF controls. So it can totally be done, I promise! However, you have a lot of other factors also. I noticed that you are using either Infragistics or DevExpress ribbon bar. I also noticed that something in your dialog is moving the controls after their initial render. So you are fighting more than a data load issue. When your form comes up and moves 10 pixels to the left and up then something else is going on. I know that at one point you were considering inheriting from the XtraForm. Did you do that? Do you have any handlers in your form? There is more going on than what you showed me. Just changing the data load alone will more than likely not resolve your issue. I would first figure out why your dialog is re-rendering at least twice on instantiation and then moving. All of these things need to be figured out as well. You are right in that you are dealing with a simple form...but clearly you have something in the mix that is causing an issue that is outside of the norm. Outside of looking at your code and debugging it the only thing I can tell you to do is to work backwards. Copy your form over so you can get back to ground zero (or create a new form). Then add one piece at a time until you can determine where the trouble spot is. This is going to be the only way to diagnose where your issue is.
|
By Trent L. Taylor - 4/12/2008
One other thing I thought about that can improve performance is to preload your assemblies into the AppDoman. This will improve the initial instantiation speed the first time. An assembly reference won't be loaded into the AppDomain until it is first used. So if you preload these it will speed up the performance the first time an assembly is used. Just another idea.
|
By Trent L. Taylor - 4/12/2008
OK...a final, final thought I am working from home today and on a really slow machine (I totally need to rebuild my home computer). I am also talking to a remote data source in another town via a cable modem VPN. On top of that, I just installed a new version of Camtasia and I didn't adjust anything and when I ran the app with Camtasia running and it slowed my machine WAY down. But even with all of that, the screens loaded pretty quickly. When running in a normal environment there is no lag or delay at all. I just though you might want to see what I was talking about. I have attached a video here running a very small portion of our medical application. So you can see this coming from a large scale real-world application.
|
By Trent L. Taylor - 4/14/2008
Edhy,I was testing something in the CRM sample and noticed a similar behavior to your video. One thing that you can do to resolve this very easily is to lock the screen once a handle is created and then unlock it once it is shown: Protected Overrides Sub OnHandleCreated(ByVal e As System.EventArgs) MyBase.OnHandleCreated(e) MicroFour.StrataFrame.Tools.LockScreen.Lock(Me) End Sub Protected Overrides Sub OnShown(ByVal e As System.EventArgs) MyBase.OnShown(e) MicroFour.StrataFrame.Tools.LockScreen.Unlock() End Sub I will play with is some more later to see what events are being raised and what the MDI client is doing, but this should give you a quick fix. Note: If you use this in conjunction with the non-transparent controls...it is instantanious! No flicker at all!
|
By Edhy Rijo - 4/14/2008
Hi Trent,Sorry I could not get back to you earlier, I was out today the whole day. Ok, I am not sure where to put this code, in the Main Form or in one of the maintenance forms? Even thought I tried on both and the result was basically the same, the rendering is pretty slow.
|
By Trent L. Taylor - 4/15/2008
Edhy,I reproduced your problem through an MDI environment identically to you video...so you must be placing the code in the wrong places or have something else that is overriding the locks. Ok, I am not sure where to put this code, in the Main Form or in one of the maintenance forms? The maintenance form...NOT the main form!!! Even thought I tried on both and the result was basically the same, the rendering is pretty slow.
I took the CRM Sample Application and reproduced the problem, took the Customer Maintenance Form and added the code above, I also changed the Themed controls to not render transparents and render with solid backgrounds and all issues that you were talking about...to the "T" went away.
|
By Edhy Rijo - 4/15/2008
Hi Trent,Thanks again for the support. I tried your code in the CRM and as you said, it worked as expected. Now I put the code in the Maintenance Form as suggested in my project and what I am seeing is that the form will not render until it is moved by me using the mouse. Please take a look at this small video sample that illustrate what I am experiencing: http://www.progytech.com/videos/SF_Sample2/SF_Sample2.html Just to clarify: - The MDI MainForm is using the DevExpress Ribbon control (not the Ribbon form class).
- The Maintenance Form is using SF controls including the modified ListView (SynchListView) posted by Greg McGuffey in this link http://forum.strataframe.net/FindPost14966.aspx
|
By Trent L. Taylor - 4/15/2008
This is turning into somewhat of a lesson on windows, rendering, and handles....all things that are related to WinForms development versus StrataFrame itself. We too ran into rendering issues in some of our applications...and we had to stop, figure out where the issues were, and work through them. One of the primary issues that we ran into were MDI forms and the MDIClient class.We wrote our own MDI environment for our medical application so that rendering would be faster. However, one thing that is generally a bad idea is to just set the IsMDIContainer property to true...many issues come from doing this. You are always better of creating an MDIClient class and then adding it to your form, which will in affect turn that form into an MDI. I have attached a sample of how to do this. You can then take this to the next level by adding form loading logic, etc, when it is added to the MDI. You can render the back of the MDI client (in this sample I just set the background to white). But there are a lot of things that you can do. This at least gives you more control than just setting the IsMDIContainer proeprty to True and then you can start to create your application environment.
|
By Edhy Rijo - 4/15/2008
Thanks Trent,Will check your sample and implement in my current project. Once again, your help is must appreciated.
|
By Edhy Rijo - 4/15/2008
Trent L. Taylor (04/15/2008) This at least gives you more control than just setting the IsMDIContainer proeprty to True and then you can start to create your application environment.Trent, You certainly nailed the problem with this sample solution. In no time I was able to replace the old code in my Main Form and now the rendering problem is virtually gone. I took the liberty of adding some functionality to the LaunchForm method that will do the following: - Before creating a new form object, check through the _MDI form's collection for an existing instance.
- If found then activate that instance and bring it to the front.
Here is the changed code: ''' <summary>''' Common method for automatically launching a form and making it an MDI child.''' If the form exist in the _MDI collection then show it to the user instead.''' This functionality could be controlled by passing a 2nd parameter''' </summary>''' <param name="FormType"></param>''' <remarks></remarks>Private Sub LaunchForm(ByVal FormType As System.Type) '-- Establish Locals Dim loForm As Form '-- Create the form loForm = CType(Activator.CreateInstance(FormType), Form) For Each currentForm As Form In Me._MDI.Controls If currentForm.Name = loForm.Name Then '-- If the form is minimized then restore it. If currentForm.WindowState = FormWindowState.Minimized Then currentForm.WindowState = FormWindowState.Normal End If '-- Show the form on top of the others. currentForm.BringToFront() Exit Sub End If Next '-- Set the MDI parent loForm.MdiParent = Me '-- Show the form loForm.Show() End Sub
|
By Trent L. Taylor - 4/15/2008
Glad it helped you with your problem.
|
|