2009-10-26 12 views
13

Mój program umieszcza ikonę na pasku zadań, ponieważ użytkownik może do niej zminimalizować. Jeśli jednak aplikacja ulegnie awarii lub zatrzymam działanie aplikacji w VS, pozostawi ona w niej ikonę, dopóki nie zatrzymam na niej myszy. Czasami spojrzę tam i będzie około 10 ikon.Jak zapobiec pozostawianiu ikony w zasobniku systemowym przy wyjściu?

Czy mogę się upewnić, że ikona zniknie?

Odpowiedz

21

Nie ma mowy aby to zrobić. System Windows nie odpytuje twojego programu, aby sprawdzić, czy wciąż żyje. Dlatego Twoja ikona pozostanie w zasobniku systemowym, dopóki nie powiesz jej, aby opuściła (normalne wyjście), lub użytkownik robi coś, co inicjuje wywołanie twojego programu (takie jak najechanie kursorem myszy). Tylko wtedy powłoka będzie wiedziała, że ​​twój program umarł i musi wyczyścić twoją ikonę.

+0

Więc nie ma zdarzenia, które mógłbym zdobyć na wypadek śmierci programu? – Malfist

+0

Nie, nie ma zdarzenia. To jest "normalne" zachowanie ... każda aplikacja, która ma ikonę w zasobniku systemowym, pozostawia ikonę, gdy wychodzi poza normalnie. – jrista

+1

Jest bardzo mało prawdopodobne, że nie będziesz miał okazji wyczyścić ikony. AppDomain.ProcessExit jest całkiem dobrym wydarzeniem do wysłuchania wyjścia procesu. Jeśli nie wywołasz funkcji Environment.FailFast(), będzie ona prawdopodobnie wywoływana nawet w 'katastrofalnych' okolicznościach –

3

Przed wyjściem, ustaw właściwość NotifyIcon Visible na false.

+1

Ale kasuje je, gdy program wychodzi poprawnie. Ale jeśli program umiera, jest zabity lub ulega awarii, opuszcza ikonę. – Malfist

+2

Sądząc po liczbie produktów, które mają to samo zachowanie, trudno jest rozwiązać ten problem. –

+0

Chociaż nie jest to najlepsze rozwiązanie, ale jest to dobra sztuczka, aby szybko go rozwiązać! – Arash

3

Należy wywołać utylizację na urządzeniu NotifyIcon, aby opuścił tacę.

EDYCJA: Istnieje zdarzenie, które można podłączyć do pliku Program.cs. Dla wszystkich aplikacji systemu Windows, musisz coś takiego:

[STAThread] 
    static void Main() 
    { 
     Application.EnableVisualStyles(); 
     Application.SetCompatibleTextRenderingDefault(false); 
     Application.Run(new Form1()); 
    } 

Klasa Aplikacja posiada kilka zdarzeń można skorzystać z wiedzieć, kiedy umiera aplikacja:

 Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException); 
     Application.ApplicationExit += new EventHandler(Application_ApplicationExit); 
+0

Ale gdzie/kiedy? – Malfist

+1

PO wspomina, że ​​widzi problem tylko wtedy, gdy jego aplikacja umiera lub on go zabija. W takich sytuacjach funkcja Dispose() nie zostanie wywołana. –

4

Masz kilka opcji:

1) Napisać korzeniowy strukturze obsługi wyjątku, który zapewnia zniszczenie ikonę przed wyjściem. Ten wymaga trochę wysiłku - ale zasadniczo można dodać do systemu Windows własną nieobsługiwaną procedurę obsługi wyjątków, która będzie wywoływana w przypadku wielu form "boomu", co pozwoli ci na ostatnią szansę oczyszczania.

2) Napisz aplikację monitorującą, która śpi na głównym uchwycie procesów, i zabija ikonę po jej pobudzeniu (główna aplikacja zginie). Aby ten drugi scenariusz działał dobrze, najprawdopodobniej będziesz chciał, aby główny proces NIE zabijał samej ikony - lub możesz stworzyć sposób, aby poinformować aplikację monitorującą, że powinna wyjść z niszczenia ikony (czy aplikacja monitorująca śpi zarówno na uchwycie procesu, jak i nazwanym wydarzeniu - a jeśli zostanie on obudzony przez zdarzenie, po prostu umiera bez czyszczenia po głównej aplikacji).

+0

D'oh - Powinienem był zauważyć język. Opcja nr 1 jest dostępna dla C lub C++, ale nie jestem pewien, czy jest ona dostępna dla aplikacji C# - więc możesz być zmuszony do zrobienia # 2. – Mordachai

+0

# 2 jest w każdym razie bardziej niezawodną opcją. # 1 nie byłby dobry, gdyby proces został zabity w Menedżerze zadań lub, jak wspomniał OP, gdyby jeden z nich nagle przerwał sesję debugowania. –

-1

Możemy ukryć trayIcon przed zamknięciem formularza. Dodaj wydarzenie FormClosing

NotifyIcon ni; 
... 
... 
private void MainForm_FormClosing(object sender, FormClosingEventArgs e) 
{ 
    ni.Visible = false; 
} 
Powiązane problemy