.NET ImageList becomes corrupt occasionally - c#

With a Winforms .net application, we have an issue where an image list occasionally becomes corrupted.
By corrupted I mean that the count of the number of images will be wrong and/or the images may have been replaced by system images (like dialog box icons).
For example, the screenshot below shows the imageInfoCollection showing the correct number, but the count showing the incorrect number.
The image list is on a form that is opened repeatedly by the user throughout the use of the application. The image list is used by a tab control on the form.
The issue occurs only occasionally, anywhere between every 5 and 20 times of opening the form.
The code to load the imagelist is built by the designer, and uses images from the resources:
this.imageListCallTakingScreen.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageListCallTakingScreen.ImageStream")));
this.imageListCallTakingScreen.TransparentColor = System.Drawing.Color.Transparent;
this.imageListCallTakingScreen.Images.SetKeyName(0, "spinner.png");
this.imageListCallTakingScreen.Images.SetKeyName(1, "recommendation-star.png");
this.imageListCallTakingScreen.Images.SetKeyName(2, "recommendation-star_red.png");
this.imageListCallTakingScreen.Images.SetKeyName(3, "recommendation-star - Transparent.png");
this.imageListCallTakingScreen.Images.SetKeyName(4, "Initialisation_fail16.png");
this.imageListCallTakingScreen.Images.SetKeyName(5, "information_white.png");
this.imageListCallTakingScreen.Images.SetKeyName(6, "Check-icon.png");
The imagelist isn't used anywhere other than in the designer.cs code to create it and wire it up to the tab control (except for the error trapping line I have put in):
Ideas? We are stuck on this one and google doesn't turn much up.

The imageInfoCollection field properly tracks the number of images you have in the ImageList. The Count property tracks the number of images that are actually present in the native Windows imagelist control.
There's only one way those values could have a mismatch that I can think of. Your program is leaking GDI object handles. A fairly common problem in Winform apps. That works for quite a while until you reach the operating system quota for such handles, after you've consumed 10,000 of them then Windows stops allowing you to create more. The error checking in the .NET wrapper class is not entirely kosher so this can happen without an exception getting generated. You'll see some more strange painting artifacts when you hit that limit btw.
You can get a basic diagnostic from Task Manager, Processes tab. Use View + Select columns and tick GDI Objects and USER objects. Observe these values while you operate the program like a user would. A steadily climbing value for GDI Objects spells doom. A hint that you are forgetting to use the using statement to dispose System.Drawing objects. And the garbage collector not running often enough to keep you out of trouble. You need to fix this in your code so the counter remains stable at, say, no more than several hundred objects.
A steadily climbing value for USER Objects is also a very common Winforms bug. That's a pretty fatal one, it will jack-up the GDI object count as well and the GC cannot fix this problem. This will happen when you remove controls in your code with Controls.Remove/At() or Controls.Clear() and forget to dispose the removed control objects.

Related

WPF: Optimize loading time and memory usage of Canvas having 5000+ elements

As shown in the image above, my application has ~5000 elements drawn to a Canvas.
Due to this large number of elements, I've got two problems:
Memory usage is ~3 GB
The loading time is ~4 minutes
I need to optimize this.
E.g. as shown in the image, we are using combo box to bind item source 5000 with a list of string items.
Is there any way we can use the same items source location instead of creating new one every time for each one of the 5000 elements? That could solve the memory usage issue...
About the loading time, I don't worry so much now.
However, I currently have a progress bar which displays the loading progress of all those elements, but it does not work as expected (it closes before loading). I think it is so because we can't run two STA threads at the same time.
How can I keep this progress bar working until every element is successfully loaded to the canvas? I didn't find any event which informs the successful loading of elements to the canvas.
Any ideas on how to improve this application? Suggestions are welcome.

Spell check textbox in Win10 - Slow

I'm using the built in spell checker in WPF. It was working just fine until I had users start upgrading to windows 10... I think the issue is that it's being used for a lot of small text boxes. My application presents a grid (Telerik's TreeListView) with text boxes for one of the columns which i want spell checked. I need to be able to provide a custom dictionary to the spell checker; the only way I was able to do this was to subscribe to the textbox loaded event and add the paths in as follows:
TextBox tb = sender as TextBox;
tb.ContextMenu = ctx_Spell;
IList dcts = SpellCheck.GetCustomDictionaries(tb);
dictsList.Add(dcts);
if (KMApplication.Settings.UserDictionary != null)
{ dcts.Add(KMApplication.Settings.UserDictionary); }
foreach (Uri dct in KMApplication.Settings.RevitDictonaries)
{ dcts.Add(dct); }
Granted this calls the add for each and every text box which seems terribly wasteful, but it seemed to be working just fine with little noticeable lag and only on load up. However now on Windows 10 it seems to be a ridiculous lag. On my Windows 8.1 machine I load up a file with a few thousand rows and it appears in about 3 or 4 seconds; on my Windows 10 box, it appears in about 10-15 minutes. If I comment out the custom dictionaries portion of the above code it's back to about 3-4 seconds on either machine.
Does anyone know a better way to do this? Or if there is some way around it in Win10?
We have experienced a similar issue and saw improved performance by avoiding re-registering custom dictionaries on every TextBox control during load.
Unfortunately, we hit another issue with the way custom dictionaries are handled which can also result in very long loading times if you have even a small number of TextBox controls.
When a WPF application registers a custom dictionary in .NET 4.6.1 on Windows 8.1/10, a temporary dictionary file is created in %localappdata%\Temp and this is registered in the multistring value _GLOBAL_ in the registry key "Computer\HKEY_CURRENT_USER\Software\Microsoft\Spelling\Dictionaries".
If the _GLOBAL_ value ends up referencing a dictionary file which does not exist, the application starts to exhibit very slow loading whenever a control with spell check enabled is initialized.
This can happen by using the "Stop debugging" button in Visual Studio and then running the Disk Clean-up or CCleaner after enough time has passed for these to delete the temp dictionary files.
We managed to fix this by clearing the _GLOBAL_ value of any links to dictionary files which did not exist. The our application began to work as expected.
We raised the following connect bug:
https://connect.microsoft.com/VisualStudio/feedback/details/2153484
Starting .NET 4.6.1 (in Win8.1 & Win10), WPF uses ISpellChecker interface exposed by the OS to implement its SpellChecker, and the performance characteristics could be somewhat different indeed.
Notably, ISpellChecker's custom dictionary registrar acts globally - it no longer acts as a per-control registration. (See KB article link below). As a result, registering the same set of dictionaries over and over for each control is wasteful and can potentially degrade your performance. Besides, the OS will just start ignoring your dictionaries when it reaches an internal limit.
Just register the dictionaries once, or use the alternative registration mechanism outlined at http://blogs.msdn.com/b/wpf/archive/2015/10/29/wpf-in-net-4-6-1.aspx and place the files under %appdata%\microsoft\spelling\.
If you need to run the same application on Win7/Win8 as well as Win8.1/Win10, you may need to detect the OS and branch your dictionary registration strategy.
In general, typical uses of custom dictionaries should continue working as usual - with little difference between .NET 4.6.1 vs previous releases.
Also see https://support.microsoft.com/en-us/kb/3088234 for additional information.
Firstly, I want to mention that I know that the post is already a few years old but I think that my answer might help someone out there who has the same problem but where the presented solutions didn't work (like myself).
What fixed it for me was to add the following code to App.config:
<runtime>
<AppContextSwitchOverrides value="Switch.System.Windows.Controls.DoNotAugmentWordBreakingUsingSpeller=true"/>
</runtime>
Alternatively you can also insert the following code after your InitializeComponent() call:
AppContext.SetSwitch(#"Switch.System.Windows.Controls.DoNotAugmentWordBreakingUsingSpeller", true);
Source 1 (XAML solution)
Source 2 (C# solution)

Limited controls in WPF Form (win32exception conflicts with 10,000 controls per window)

I have a program running fine but when it hit nearly 10,000 images in WPF form thrown exception System.ComponentModel.Win32Exception: The operation completed successfully.
it so weird, sounds poor design, but functioning well as per the requirements. Without splitting process in to multiple, is there any better way that helps in getting rid of this issue and allow users to process over 10,000 images (controls in form).
I have double checked unmanged code disposed properly and used using blocks etc..
Background : Application creates image thumbnails of PDF pages and the images are stored in cache. Application is working well in handling a big load in giga bytes though it takes fair bit of time to create images on screen .(this is an acceptable delay)
It sounds like you have reached the Windows limit of 10,000 user handles.
You might want to try batching up the processing, or maybe using a virtualizing panel like the VirtualizingStackPanel to display the images. This will only create UI controls as they are scrolled into view.

How to use BlockingCollection for image caching

I'm hoping someone may please be able to assist me with a programming solution. I currently have a machine that acquires a bitmap image of an item on a conveyor. An image is acquired from the camera about every 5 seconds. I need to store (cache in memory) the most recent 4 images or so. Almost like a stack, where each time a new image is acquired, I need it at the top of the stack and it pushes the others down such that the last (oldest) image is dropped off. I was thinking of using a collection for storing these bitmaps. When I add the bitmap I will also add the unique "key" identifying the image. Since things need to run concurrently on this machine, I was thinking of using a BlockingCollection such that they run on their own thread using the producer-consumer method (from what I have researched). However, I have no experience with this and no idea how to get started.
After these images are taken and cached into my collection, the item moves down the conveyor a little more and then another image is taken of the same part with a different camera. An inspection is performed on this second image and if it is determined a "fail", I need to save this second image out to disk AND save the previous image of that same part (from the first camera). This is why I need to cache them and be able to retrieve them.
NOTE: The cameras are NOT next to one another such that the second image is acquired immediately after the first. Up to 2 or 3 parts may have gone past the first camera before they reach the second camera (as they go through a process in-between).
My idea is to
1). In my GUI thread I want to create an instance of a collection class to store the bitmap images and along with their unique keys. When an item is added to the collection the add method will determine the collection count and automatically remove the oldest one.
2). At certain instances (a "fail" at the second camera as described above) I will need to check/grab an image from the collection. I would like to use the TryTake method so that it will obtain the bitmap (based on the key that I provide) from the collection. I don't want the grabbing of the image from the collection to interfere with the possibly of adding one at the exact same moment.
3). Lastly, once I've obtained the image from the collection, I need to save that image out to disk along with the second image. I would like the save process to run on its own thread as well so that it doesn't impact performance or the ability of the app to need to work with the collection during a save process.
I have no idea how to get started on this except to make a class called cImageCache and add a property for the unique key. Any coding examples/help in either C# or VB.NET would be greatly appreciated! Thank you very much for your time.
Kindest Regards
I suggest using an ObjectCache. Come up with a key for the item, and store it. You can set it to be removed from the cache after a certain amount of time. It is threadsafe.

Winforms issue - Error creating window handle [duplicate]

This question already has answers here:
"Error Creating Window Handle"
(11 answers)
Closed 10 years ago.
We are seeing this error in a Winform application. Can anyone help on why you would see this error, and more importantly how to fix it or avoid it from happening.
System.ComponentModel.Win32Exception: Error creating window handle.
at System.Windows.Forms.NativeWindow.CreateHandle(CreateParams cp)
at System.Windows.Forms.Control.CreateHandle()
at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
at System.Windows.Forms.Control.CreateControl()
at System.Windows.Forms.Control.OnVisibleChanged(EventArgs e)
at System.Windows.Forms.ButtonBase.OnVisibleChanged(EventArgs e)
Have you run Process Explorer or the Windows Task Manager to look at the GDI Objects, Handles, Threads and USER objects? If not, select those columns to be viewed (Task Manager choose View->Select Columns... Then run your app and take a look at those columns for that app and see if one of those is growing really large.
It might be that you've got UI components that you think are cleaned up but haven't been Disposed.
Here's a link about this that might be helpful.
Good Luck!
The windows handle limit for your application is 10,000 handles. You're getting the error because your program is creating too many handles. You'll need to find the memory leak. As other users have suggested, use a Memory Profiler. I use the .Net Memory Profiler as well. Also, make sure you're calling the dispose method on controls if you're removing them from a form before the form closes (otherwise the controls won't dispose). You'll also have to make sure that there are no events registered with the control. I myself have the same issue, and despite what I already know, I still have some memory leaks that continue to elude me..
See this post of mine about "Error creating window handle" and how it relates to USER Objects and the Desktop Heap. I provide some solutions.
This problem is almost always related to the GDI Object count, User Object count or Handle count and usually not because of an out-of-memory condition on your machine.
When I am tracking one of these bugs, I open ProcessExplorer and watch these columns: Handles, Threads, GDI Objects, USER Objects, Private Bytes, Virtual Size and Working Set.
(In my experience, the problem is usually an object leak due to an event handler holding the object and preventing it from being disposed.)
I think it's normally related to the computer running out of memory so it's not able to create any more window handles. Normally windows starts to show some strange behavior at this point as well.
I got same error in my application.I am loading many controls in single page.In button click event i am clearing the controls.clearing the controls doesnot release the controls from memory.So dispose the controls from memory.
I just commented controls.clear() method and include few lines of code to dispose the controls.
Something like this
for each ctl as control in controlcollection
ctl.dispose()
Next
Well, in my case it was definitely the USER Objects that were out of control. I looked in the Windows Task Manager and sure enough, the USER Objects count was at 10'000 exactly.
I am dynamically embedding property and list sheets in Tab Pages by setting the Parent property of the property or list sheet's container panel to that of the Tab Page. I am conditionally recycling or re-creating the property and list sheet forms depending on the type of collection being listed or class type of the object being inspected.
NB: In Delphi, all controls had an Owner and a Parent property. Even if one changed the Parent property of a control, it would still be disposed by its owner when the owning control got destroyed.
In C# it seems that if a control e.g. a Panel is programmatically reassigned from, say, a Form to a Tab Page by changing the Panel.Parent property, calling Dispose() on the Form won't dispose the Panel, neither will calling Controls.Clear() on the Tab Page. Even a direct call Panel.Dispose() won't actually dispose it, unless its Parent is manually set to null beforehand.
I added a check that makes it work...
if (_form.Handle.ToInt32() > 0)
{
_form.Invoke(method, args);
}
it is always true, but the form throws an error without it.
BTW, my handle is around 4.9 million
Definitely too many handles(memory leak issue):
IT Jungles: System.ComponentModel.Win32Exception: Error creating window handle
The out of memory suggestion doesn't seem like a bad lead.
What is your program doing that it gets this error?
Is it creating a great many windows or controls?
Does it create them programatically as opposed to at design time?
If so, do you do this in a loop? Is that loop infinite?
Are you consuming staggering boatloads of memory in some other way?
What happens when you watch the memory used by your application in task manager? Does it skyrocket to the moon? Or better yet, as suggested above use process monitor to dive into the details.

Categories