0

So, I have a [.NET] program that implements a NotifyIcon that persists in the Notification Tray in Windows for the entire time that the program runs. When I first execute the program, and for a small time afterwards, the NotifyIcon and associated ContextMenuStrip work an absolute charm.

However, after some time of the machine being in a lower power state or just idle for a few hours, when trying to access the Context Menu, it can take up to 2 seconds for the object to draw.

Is there some persistence need to define to get the menu to respond faster? Have I enabled an incorrect event that is firing a cleanup of resources?

Edit

It would seem that I have 3 options to see if I can get this to work:
1. Insert a SecureString object into the ContextMenuStrip object; this assumes that by having the SecureString inside the ContextMenuStrip, the whole object will be treated the same and will not be page swapped
2. Create a Timer that touches the ContextMenuStrip on interval in some manner to keep it in memory
3. Alter Process.MinWorkingSet when the app has completed initial launch to try (read: hope) that the ContextMenuStrip object is kept alive and not something else

I really am not a fan of items 2 or 3; 3 especially. I am going to try item 1 and see if it works.

Thanks for the responses so far!

SmithPlatts
  • 773
  • 7
  • 20
  • My first guess would be that you are reading something from a hard disk drive when showing the ContextMenu and that hard drive had to power up. Windows turns off hard drives by default after some inactivity. – Trevor Elliott Oct 20 '13 at 06:35
  • Processes that are idle for a long time will have their pages swapped out. Page-faulting them back into RAM takes time. – Hans Passant Oct 20 '13 at 07:24
  • @TrevorElliott I did think of this but was able to confirm that my power settings do not turn off, or spin down, the HDD and as originally stated, the issue is apparent even when the machine has just been idle and not in any sort of _sleep_ state. – SmithPlatts Oct 20 '13 at 21:47
  • @HansPassant cheers for that suggestion/explanation; I was curious of that but could not for the life of me remember how to describe it. Is there some properties I can specify to help keep these pages in RAM? They are so small it isn't funny and should be of no issue to keep persistent ... – SmithPlatts Oct 20 '13 at 21:47
  • You can tinker with the Process.GetCurrentProcess().MinWorkingSet property. That's not a very reasonable thing to do and has no guarantees, a .NET process is never small. – Hans Passant Oct 20 '13 at 21:51
  • @HansPassant cheers for the response; I have a couple of options (see edit) and will see what does/doesn't (shouldn't) work (be used) – SmithPlatts Oct 22 '13 at 12:04

1 Answers1

0

From my testing it would appear that option 1 outlined in the questions edit has done the trick ... for the most part.

As has been stated, and of which I already understood, C# is a managed language; making memory management difficult.
However, by adding a new SecureString() object to one of the ContextMenuStrip menu items' Tag attributes, the menu object will persist in RAM.

There are, sadly, two primary caveats to this approach:
1. If the machines RAM gets hit HARD, the SecureString object is either forcibly discarded or decoupled from the encompassing object and the page fault/swap is performed. I am unsure as to whether it re-couples together again post scenario, but it seems to do ok.
2. If the machine is put to sleep or hibernate, the whole app gets page swapped and the SecureString is most definitely discarded. To aid in these situations, I have a SessionSwitchEventHandler that detects if the machine has been unlocked and creates a new SecureString() object in a menu items' Tag attribute and re-associates the ContextMenuStrip object to the NotifyIcon.ContextMenuStrip

Although it's not the best solution, it does work and is better then creating a timer to touch the menu [shudders] or, worse, playing with the Process.MinWorkerSet [takes a shower at the thought]

Thanks again to those who took part in the question and helped think further to find a solution.

SmithPlatts
  • 773
  • 7
  • 20