Hi all,
I've witnessed this big red cross appearing in place of an UltraGrid when calls wern't marshalled correctly to the main/UI thread when making use of the control.
I have an application that I've ensured only accesses controls from the main/UI thread.
Recently, we've been stress-testing our application and have witnessed this red cross again. This time it appears in place of a ribbon/toolbar control. It's only ever appeared when we're using excessive amounts of memory - causing some components of the application to become sluggish. One example is when the user creates a scatter UltraChart component that has about 40,000 points of data.
So I have a couple of questions concerning this issue:
I'd appreciate any more information regarding this red cross. From what I've read so far:
Any information what so ever (even simply to clarify my current understanding is correct) would be greatly appreciated.
Cheers,
Richard
Can anyone help with this? I've now noticed it can occur when using a low amount of memory, so that doesn't seem to affect it. The stack trace I'm getting from the unhandled exception is:
************** Exception Text **************
System.ArgumentException: Parameter is not valid.
at System.Drawing.Graphics.GetHdc()
at Infragistics.Win.FormattedLinkLabel.PositionElementsCache.MeasureTextGDIOrThemed(String text, Font font, TextFormatFlags textFormatFlags)
at Infragistics.Win.FormattedLinkLabel.PositionElementsCache.MeasureCharacterRangesGDI(String text, Font font, TextFormatFlags textFormatFlags, CharacterRange[] ranges)
at Infragistics.Win.FormattedLinkLabel.PositionElementsCache.ReMeasureParts(String text, Int32[] parts, Single[] widths, Int32 partStartIndex, Int32 partEndIndex, Font font, Single& lineHeight)
at Infragistics.Win.FormattedLinkLabel.PositionElementsCache.MeasureParts(String text, Int32[] parts, Font font, Single& lineHeight)
at Infragistics.Win.FormattedLinkLabel.NodeText.TextLayoutInfo.Measure(PositionElementsInfo& info)
at Infragistics.Win.FormattedLinkLabel.NodeText.PositionSelf(PositionElementsInfo& info)
at Infragistics.Win.FormattedLinkLabel.NodeBase.PositionHelper(PositionElementsInfo& info)
at Infragistics.Win.FormattedLinkLabel.NodeBase.Position(PositionElementsInfo& info)
at Infragistics.Win.FormattedLinkLabel.NodeBase.PositionChildNodes(PositionElementsInfo& info)
at Infragistics.Win.FormattedLinkLabel.NodeBlock.PositionChildNodes(PositionElementsInfo& info)
at Infragistics.Win.FormattedLinkLabel.NodeBase.PositionElements(IFormattedLinkLabelOwner owner, UIElement containerElem, Rectangle containerRect, Boolean calcIdealLayoutSize, Size& layoutSize)
at Infragistics.Win.FormattedLinkLabel.FormattedTextUIElement.PositionElementsHelper(Rectangle layoutRect, Boolean setElemRectToIdealSize)
at Infragistics.Win.FormattedLinkLabel.FormattedTextUIElement.PositionChildElements()
at Infragistics.Win.UltraWinToolbars.RibbonCaptionUIElement.PositionChildElements()
at Infragistics.Win.UIElement.VerifyChildElements(ControlUIElementBase controlElement, Boolean recursive)
at Infragistics.Win.UIElement.DrawHelper(Graphics graphics, Rectangle invalidRectangle, Boolean doubleBuffer, AlphaBlendMode alphaBlendMode, Boolean clipText, Boolean forceDrawAsFocused, Boolean preventAlphaBlendGraphics)
at Infragistics.Win.UIElement.Draw(Graphics graphics, Rectangle invalidRectangle, Boolean doubleBuffer, AlphaBlendMode alphaBlendMode, Boolean forceDrawAsFocused, Boolean preventAlphaBlendGraphics)
at Infragistics.Win.ControlUIElementBase.Draw(Graphics graphics, Rectangle invalidRectangle, Boolean doubleBuffer, AlphaBlendMode alphaBlendMode, Size elementSize, Boolean preventAlphaBlendGraphics)
at Infragistics.Win.ControlUIElementBase.Draw(Graphics graphics, Rectangle invalidRectangle, Boolean doubleBuffer, AlphaBlendMode alphaBlendMode, Size elementSize)
at Infragistics.Win.ControlUIElementBase.Draw(Graphics graphics, Rectangle invalidRectangle, Boolean doubleBuffer, AlphaBlendMode alphaBlendMode)
at Infragistics.Win.UltraControlBase.OnPaint(PaintEventArgs pe)
at Infragistics.Win.UltraWinToolbars.UltraToolbarsDockArea.OnPaint(PaintEventArgs pe)
at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer)
at System.Windows.Forms.Control.WmPaint(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
The big red "X" occurs any time an exception occurs inside the OnPaint method of a control. Since the controls have been around so long and are so well-used and therefore well-tested, we rarely find bugs in the painting code any more. But it can happen.Does the exception always occur with the same call stack which includes a reference to the FormattedLinkLabel?Is the exception always on a call to GetHdc?Or does the exception vary each time it occurs?If the exception always happens on the same call to GetHdc being called from MeasureTextGDIOrThemed, then this is likely a bug in the FormattedLinkLabel.If the exception varies each time it occurs, then it's probably a memory or threading issue.
Hi Mike,
Thanks for taking a look at this.
Mike Saltzman"]Does the exception always occur with the same call stack which includes a reference to the FormattedLinkLabel?
Yes, the call-stack in the exception is always exactly the same.
After having a look at it further, we established it was occuring when a Form containing an UltraExplorerBar is shown from the Form that contains the Ribbon. The item that was selected in the UltraExplorerBar when the Form was displayed last is selected upon displaying the Form (in the construct). The error occured intermitently, only when it selected an item in the bar that was not the default selected item. It always occured soon after displaying the form, but it could take up to 10 iterations of closing the form and reopening it too see the error.
To select the item in the explorer bar in the Form, we set the SelectedGroup of the explorer bar to the group that contained the appropriate item, and then checked the appropriate item.
I modified this so that instead, the ActiveGroup of the explorer bar is set to the group that contains the appropriate item. We perform the SelectActiveGroup action on the explorer bar using the PerformAction method, and then check the item in the same way. This appears to have worked!
So I'm guessing there's an issue relating to the focus of the groups or something?
Out of interest, does this still sound like a bug, or it simply bad practice to select things in an Infragistics Control by setting the SelectedX property e.g. SelectedGroup?
Thanks for the information Mike!
Hi Richard,
Richard said:Out of interest, does this still sound like a bug, or it simply bad practice to select things in an Infragistics Control by setting the SelectedX property e.g. SelectedGroup?
It's impossible to say for sure without being able to duplicate the issue. It could be a timing or threading issue, but it's certainly possible that it's a bug in the ExplorerBar. Perhaps setting the SelectedGroup is forcing it to paint too early before some part of the control has been properly initialized.
If you can reproduce the issue in a small sample project and post it here, we could look into it further.
Thanks Mike, I'll keep an eye out for it and when I get a chance I'll post a sample. Thanks for your help.
Hello Johnie,
Thank you for your response.
What you're seeing there is not actually a leak. What you're seeing is some objects being retained after they are created for optimization purposes. I've modified your sample to remove all of the Infragistics controls and added a second MDI child form that is opened by "button1". If you run it, you'll see the same kind of behavior in regards to the GDI and USER objects.
It is still very possible that your application has a GDI/USER object leak, but the sample you provided doesn't reproduce that.
Hi Dave,
The reason we can't duplicate the issue with your sample, is because you are dynamically creating and then disposing that created object. This doesn't represent a real-world application however. I've modified the sample for you, and in the process, I have come to a better understanding of the leak behavior.
The sample contains an MDI parent with a button. When the button is clicked, a child window is opened up. When the child window is closed, the counts do not drop to the original value. It should be noted that the object counts will not go up past this new number on subsequent window open/closes. I don't know how to make that statement clear, so I'm sorry it doesn't make any sense. I've used our real application and took step-by-step screenshots (the word document), which will demonstrate what I mean. Using the new sample project, here is what happens.
Obviously, this issue wouldn't occur for a small application (like our sample). However; our application contains many, many windows, so as windows are opened and closed over time, this number grows higher and higher.
Thanks,Johnie
Thank you for your response. I should have been more clear with my previous response. When I run my sample, I don't see the number of GDI objects or USER objects going up and up without stop.
I've attached my sample so you can see if it reproduces the issue on your end. If it doesn't, let me know how I can modify it so it does reproduce the issue.
Dave,We can verify the problem with Windows XP, 7, and 8.
Here is what you will need to do for an easy test.
By default, Windows allows 10,000 user objects and 10,000 GDI objects per application instance. What you are testing for is a slow leak, and obviously 10,000 objects is a lot to work your way up to.
Luckily for us, this "quota" is a setting in the Registry, so we can first modify the registry to a more manageable number, say 1,000 user objects and 500 GDI objects.
GDI Object Limit:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\GDIProcessHandleQuotaUser Object Limit:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\USERProcessHandleQuota
I only changed one of these at a time, and I used a computer that didn't have any other programs running. To monitor, open Task Manager and add columns User Objects and GDI Objects.
Now that you have your settings to a easily manageable number, open a project that has lots of Infragistics controls and many child windows that also have Infragistics controls. As you continue to open and close windows, you will see that the GDI Objects and User Objects will slowly creep up, and once they hit their limit, you will get the red box.
The decompiled code I provided in my earlier post is only one place where we found this slow leak in the library, we only looked in this one place though, so it's likely in more places.
Thanks,Johnie Karr
I'm attempting to reproduce the issue you described, but I'm not able to. Which version of Windows are you using?