sematt
sematt

Reputation: 29

C# - "Not enough storage is available to process this command" exception message

This exception was thrown on one of our running systems at work. This exception has happened two times so far within the last 6 weeks on this machine. The first time it happened, we did not have correct logging in place to display the full stack trace, so I can only see that it was coming from the DataDisplayRealTimeViewModel.SetSeriesVisibilty() method from that class. The most recent time it happened, we had correct logging and the stack trace below was shown.

Stack Trace:

Unhandled exception message: Not enough storage is available to process this command
Unhandled exception stack trace:    at MS.Win32.UnsafeNativeMethods.RegisterClassEx(WNDCLASSEX_D wc_d)
   at MS.Win32.HwndWrapper..ctor(Int32 classStyle, Int32 style, Int32 exStyle, Int32 x, Int32 y, Int32 width, Int32 height, String name, IntPtr parent, HwndWrapperHook[] hooks)
   at System.Windows.Interop.HwndSource.Initialize(HwndSourceParameters parameters)
   at System.Windows.Interop.HwndSource..ctor(HwndSourceParameters parameters)
   at System.Windows.Window.CreateSourceWindow(Boolean duringShow)
   at System.Windows.Window.CreateSourceWindowDuringShow()
   at System.Windows.Window.SafeCreateWindowDuringShow()
   at System.Windows.Window.ShowHelper(Object booleanBox)
   at System.Windows.Window.Show()
   at Chromatogram.DataDisplay.Control.DataDisplayRealTimeViewModel.<>c__DisplayClass210_0.<SetSeriesVisiblity>b__0()
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)

After looking online, I came across this post. This led me to looking into monitoring the Atom Table. I found this tool online to help monitor the atom table so I can check the entries. After letting the machine run over the weekend, I can see a lot of entries with the name HwndWrapper[OurApplicationsName;;UniqueID] --RWM.

Below is the code where the exception was thrown:

ProgressBarUserControl progressBarUserControl = null;
Application.Current.Dispatcher.Invoke((Action)(() =>
{
    progressBarUserControl = new ProgressBarUserControl();
    progressBarUserControl.Owner = System.Windows.Application.Current.Windows[0];
    progressBarUserControl.ShowInTaskbar = false;
    progressBarUserControl.Title = "Detector";
    progressBarUserControl.TitleProcess = MetaData.GetLocalizeValue("DetectorSwitchingMessage");
    progressBarUserControl.PercentageDone = "5";
    progressBarUserControl.WindowStartupLocation = WindowStartupLocation.CenterOwner;
    progressBarUserControl.Show();
}));

After we call the Show() method, we do some other logic, then at the end of this function, we call the Close() method on this object.

Application.Current.Dispatcher.Invoke((Action)(() =>
{
    if (progressBarUserControl != null)
    {
        progressBarUserControl.PercentageDone = "100";
        progressBarUserControl.Close();
    }
}));

I came across this post and the issue in this post saw similar entries to the atom table. I don't think this is the answer to my issue because, correct me if I'm wrong, the current code is not creating a new dispatcher object. It's just calling the Application's dispatcher. Side note: this code is on the UI Thread, so I believe the Invoke() may not be necessary here.

I ran some tests where the code above (not including the in between logic) was in a loop that iterated 1000 times and you can see entries being added to the atom table. I ran this test three times and averaged about 60 entries to the atom table. I ran other tests where I commented out the Show() and the Close() method and I did not see any entries added to the atom table. So it seems that this object, which inherits from the System.Windows.Window class, is creating these RWM entries and adding them to the atom table. In the Atom Table documentation, it states that

However, the entries added by RegisterWindowMessage and RegisterClipboardFormat do not get deleted until the session ends. If the user atom table has no more space and the string being passed in is not already in the table, the call will fail.

One thing to add is that these machines are meant to be running 24/7. On my test machine, that code above happens every minute and it doesn't seem to add an entry to the atom table every time the Show() method is called.

So, why is it creating so many of these entries and is there a way around this?

EDIT 1: I have looked through the suggestions in the comments and have tried various tests, but those don't seem to be cause of my issue. I should note, that I'm running a test where I comment out both of the Invoke() and the code inside, and there is still an increase of these HwndWrapper[OurApplicationsName;;UniqueID] --RWM throughout the Atom Table.

EDIT 2: Reached out to the OP on this issue since it seemed somewhat similar. Some helpful information in the comments. Still no full resolution for my issue though.

Upvotes: 1

Views: 973

Answers (1)

sematt
sematt

Reputation: 29

It's been a while, but I wanted to comment and update on my issue. I found out what was leaking atoms. We had a class that, when instantiated, would instantiate an object of the DispatcherTimer class. When you look at the internals of this class and follow it up, it creates and adds atoms to the atom table with the entry name like HwndWrapper[OurApplicationsname;;UniqueID]. This Hwnd only gets destroyed when you run the Stop() function on the object itself. About 99% of the time we created the DispatcherTimer object, we would not even use the object itself. Some shifting around fixed the leak. Now, after days of running this patch on these machines, the software does not add any extra HwndWrapper[OurApplicationsname;;UniqueID] entries to the atom table.

Upvotes: 1

Related Questions