Контекстное меню NotifyIcon замедляется

Итак, у меня есть программа [.NET], которая реализует NotifyIcon, который сохраняется в панели уведомлений в Windows в течение всего времени работы программы. Когда я впервые запускаю программу и некоторое время спустя, NotifyIcon и связанный с ней ContextMenuStrip работают абсолютно волшебно.

Однако после того, как машина некоторое время находилась в состоянии пониженного энергопотребления или просто простаивала в течение нескольких часов, при попытке доступа к контекстному меню отрисовка объекта может занять до 2 секунд.

Нужно ли определить некоторую настойчивость, чтобы меню реагировало быстрее? Включил ли я неправильное событие, запускающее очистку ресурсов?

Изменить

Кажется, у меня есть 3 варианта, чтобы проверить, смогу ли я заставить это работать:
1. Вставить объект SecureString в объект ContextMenuStrip; это предполагает, что при наличии SecureString внутри ContextMenuStrip весь объект будет обрабатываться одинаково и не будет перекачивать страницы
2. Создайте Timer, который каким-то образом касается ContextMenuStrip на интервале, чтобы сохранить его в памяти
3. Измените Process.MinWorkingSet, когда приложение завершило первоначальный запуск, чтобы попытаться (читай: надеяться), что объект ContextMenuStrip остается живым, а не что-то еще

Я действительно не поклонник пунктов 2 или 3; 3 особенно. Я собираюсь попробовать пункт 1 и посмотреть, работает ли он.

Спасибо за ответы!


person SmithPlatts    schedule 20.10.2013    source источник
comment
Мое первое предположение будет заключаться в том, что вы читаете что-то с жесткого диска при отображении ContextMenu, и этот жесткий диск должен был включиться. Windows по умолчанию отключает жесткие диски после некоторого бездействия.   -  person Trevor Elliott    schedule 20.10.2013
comment
Страницы процессов, которые простаивают в течение длительного времени, будут заменены. Чтобы вернуть их обратно в оперативную память, требуется время.   -  person Hans Passant    schedule 20.10.2013
comment
@TrevorElliott Я думал об этом, но смог подтвердить, что мои настройки питания не отключают и не замедляют работу жесткого диска, и, как было заявлено изначально, проблема очевидна, даже когда машина только что простаивала, а не в каком-либо режиме. состояние сна.   -  person SmithPlatts    schedule 21.10.2013
comment
@HansPassant приветствует это предложение/объяснение; Мне было любопытно, но я не мог вспомнить, как это описать. Есть ли какие-то свойства, которые я могу указать, чтобы сохранить эти страницы в оперативной памяти? Они настолько малы, что это не смешно, и не должно быть проблем, чтобы сохранять настойчивость ...   -  person SmithPlatts    schedule 21.10.2013
comment
Вы можете повозиться со свойством Process.GetCurrentProcess().MinWorkingSet. Это не очень разумно и не имеет никаких гарантий, процесс .NET никогда не бывает маленьким.   -  person Hans Passant    schedule 21.10.2013
comment
@HansPassant приветствует ответ; У меня есть несколько вариантов (см. редактирование), и я увижу, что работает/не (не должно) работать (использоваться)   -  person SmithPlatts    schedule 22.10.2013


Ответы (1)


Из моего тестирования выяснилось, что вариант 1, изложенный в редактировании вопросов, добился цели ... по большей части.

Как уже было сказано и что я уже понял, C# — это управляемый язык; затрудняет управление памятью.
Однако при добавлении объекта new SecureString() к одному из атрибутов Tag одного из ContextMenuStrip пунктов меню объект меню останется в ОЗУ.

К сожалению, в этом подходе есть два основных предостережения:
1. Если оперативная память компьютера СИЛЬНО повреждена, объект SecureString либо принудительно отбрасывается, либо отделяется от объемлющего объекта, и выполняется ошибка страницы/обмен. Я не уверен, будет ли он повторно соединяться вместе после сценария, но, похоже, все в порядке.
2. Если компьютер переведен в спящий режим или спящий режим , все приложение заменяется страницей, а SecureString определенно отбрасывается. Чтобы помочь в таких ситуациях, у меня есть SessionSwitchEventHandler, который определяет, была ли машина разблокирована, и создает объект new SecureString() в атрибуте Tag пункта меню и повторно связывает объект ContextMenuStrip с NotifyIcon.ContextMenuStrip.

Хоть это и не лучшее решение, но оно работает и лучше, чем создание таймера для прикосновения к меню [вздрагивает] или, что еще хуже, игры с Process.MinWorkerSet [при мысли об этом принимает душ]

Еще раз спасибо тем, кто принял участие в вопросе и помог подумать дальше, чтобы найти решение.

person SmithPlatts    schedule 26.10.2013