I have a WPF app with some winforms integration. Occasionally I will open a legacy winforms Modal Form, lets call it "UfpProductPopupForWpf".
In some circumstances which I haven't been able to identify, the UltraTextEditor seems to create and dispose a whole ton of Windows Forms in the background, for no obvious reason. See the Form disposal callstack below. My theory at this time is that it happens when no other winforms cruft is created in the app. However, if there is a WindowsFormsHost element visible somewhere on the screen already, I don't seem to get all the weird activity (creation and disposal of Windows Forms). The difference in performance is around 30 seconds.
Here is a callstack:
> System.Windows.Forms.dll!System.Windows.Forms.Form.Dispose(bool disposing) Unknown
System.dll!System.ComponentModel.Component.Dispose() Unknown
Infragistics4.Win.v16.1.dll!Infragistics.Win.DrawUtility.DecrementReferenceFormCounter() Unknown
Infragistics4.Win.v16.1.dll!Infragistics.Win.DrawUtility.ReleaseCachedGraphics(System.Drawing.Graphics g) Unknown
Infragistics4.Win.UltraWinEditors.v16.1.dll!Infragistics.Win.UltraWinEditors.TextEditorControlBase.ShouldAutoSizeHeight(out int height) Unknown
Infragistics4.Win.UltraWinEditors.v16.1.dll!Infragistics.Win.UltraWinEditors.TextEditorControlBase.SetBoundsCore(int x, int y, int width, int height, System.Windows.Forms.BoundsSpecified specified) Unknown
System.Windows.Forms.dll!System.Windows.Forms.Control.ScaleControl(System.Drawing.SizeF factor, System.Windows.Forms.BoundsSpecified specified) Unknown
System.Windows.Forms.dll!System.Windows.Forms.Control.ScaleControl(System.Drawing.SizeF includedFactor, System.Drawing.SizeF excludedFactor, System.Windows.Forms.Control requestingControl) Unknown
System.Windows.Forms.dll!System.Windows.Forms.Control.Scale(System.Drawing.SizeF includedFactor, System.Drawing.SizeF excludedFactor, System.Windows.Forms.Control requestingControl) Unknown
System.Windows.Forms.dll!System.Windows.Forms.Control.ScaleChildControls(System.Drawing.SizeF includedFactor, System.Drawing.SizeF excludedFactor, System.Windows.Forms.Control requestingControl) Unknown
System.Windows.Forms.dll!System.Windows.Forms.ContainerControl.Scale(System.Drawing.SizeF includedFactor, System.Drawing.SizeF excludedFactor, System.Windows.Forms.Control requestingControl) Unknown
System.Windows.Forms.dll!System.Windows.Forms.ContainerControl.PerformAutoScale(bool includedBounds, bool excludedBounds) Unknown
System.Windows.Forms.dll!System.Windows.Forms.ContainerControl.PerformNeededAutoScaleOnLayout() Unknown
System.Windows.Forms.dll!System.Windows.Forms.ContainerControl.OnLayoutResuming(bool performLayout) Unknown
System.Windows.Forms.dll!System.Windows.Forms.Control.ResumeLayout(bool performLayout) Unknown
UFP.LumberTrack.Shared.Windows.dll!UFP.LumberTrack.Shared.Windows.LookupControls.UfpBaseLookup.InitializeComponent() Line 96 C#
Notice the call to Infragistics.Win.DrawUtility.DecrementReferenceFormCounter which does seem to dispose of a form (which form? I do not know). It gets called over and over for every UltraTextEditor.
There is no obvious impact to the behavior of the app other than a massive 30 second delay to open "UfpProductPopupForWpf" in some cases, and instant responses to open that form in others.
Any theories? How can I get this thing to open fast in every case?
OK, here is what works. If I open some random winforms modeless window and put it off to the side, with some random IG controls inside it, then all the performance problems simply go away! From that point onwards, my WPF app can open and close a legacy winforms form (call it "UfpProductPopupForWpf") *without* a massive 30 second delay. But if I neglect to have that random winforms window open, I get the delay.
Taking it one step further I googled Infragistics winforms graphics caching and came up with a static method like so:
Infragistics.Win.DrawUtility.BeginGraphicsCaching();
It turns out that if I run this magical static method, it has the same effect as opening a random winforms window. It makes my legacy winforms stuff open without any massive delays.
So my strategy is now that I'm going to sprinkle this static method around my app like magical pixie dust and hope that it solves all my Infragistics winforms performance problems. its a wonder that Infragistics doesn't just go ahead and do this on my behalf. The overhead of running this is nothing compared to the massive delays that I was seeing before. If anyone has used a better strategy for wpf integration, please let me know.
Thanks, David
Hi David,Thank you for contacting Infragistics Developer Support.Our WinForms framework creates a thread static form, which is used to create graphics objects for the various Infragistics WinForms controls, before their handle is created (as otherwise the graphics object is created from the control itself). These graphics objects have several purposes like drawing and in your case measuring the control size. We cache this form and dispose it, only if all cached graphics are no longer in use and all UltraControlBase-derived objects (i.e. most Infragistics WinForms controls) have their handles destroyed. This is done to ensure that we keep the form as long as we need it, in order to prevent performance issues.However in your case this seems to be not working properly and that the application thinks that every UltraControlBase control has had its handle destroyed. This is obviously not the case since the UltraTextEditor is an UltraControlBase derived control. My assumption is that this is all caused by the environment that the control is used in – in a WPF application, inside a WindowsFormsHost. This code hasn’t been modified since 2009 and it is used extensively throughout our WinForms framework and, to my knowledge, this is the first time such issue is reported. This make it extremely likely that the issue happens, because of the WindowsFormsHost.Are you able to isolate this issue in a separate sample and provide it to us? This way I will be able to see exactly what is going on in your application and see why the form caching doesn’t work as it is supposed to.Note that while your workaround, prevents the performance issue it is possible that it will lead to memory leaks since calling the BeginMethodChaching method may prevent the resources from ever getting collected. So maybe at the end of your application you may still want to call ReleaseCahcedGraphics.I am looking forward to hearing from you.