Skip to content

Commit d2cffdd

Browse files
committed
Доработана выгрузка приложения в момент отображения всплывающих сообщений.
1 parent 9de0c8c commit d2cffdd

6 files changed

Lines changed: 837 additions & 5 deletions

File tree

MathCore.WPF/Notifications/README.md

Lines changed: 165 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,40 @@
1212
**7 позиций** - все углы экрана + центр
1313
**Взаимодействие** - клики мышью, клавиатура, события
1414
**Пользовательский контент** - любой XAML внутри уведомления
15+
**Не блокирует завершение приложения** - автоматическая настройка ShutdownMode
1516
**Кроссплатформенность** - .NET Framework 4.6.1 — .NET 10
1617

18+
## ⚠️ КРИТИЧЕСКИ ВАЖНО: Завершение работы приложения
19+
20+
### Как это работает
21+
22+
WPF приложения по умолчанию используют `ShutdownMode.OnLastWindowClose`, что означает завершение работы при закрытии **последнего** окна. Поскольку уведомления — это тоже окна, они **блокировали бы** выгрузку приложения.
23+
24+
**Решение:** При первом показе уведомления менеджер **автоматически** изменяет режим завершения на `ShutdownMode.OnMainWindowClose`, если `KeepApplicationAlive = false` (по умолчанию).
25+
26+
### Что происходит автоматически
27+
28+
```csharp
29+
// При первом вызове Show()
30+
ToastNotificationManager.Default.Show("Заголовок", "Сообщение", ToastNotificationIcon.Information);
31+
32+
// Менеджер автоматически выполняет:
33+
if (Application.Current.ShutdownMode == ShutdownMode.OnLastWindowClose)
34+
{
35+
Application.Current.ShutdownMode = ShutdownMode.OnMainWindowClose;
36+
}
37+
// + Подписывается на Application.Current.Exit
38+
// + Автоматически закрывает все уведомления при завершении
39+
```
40+
41+
### Результат
42+
43+
✅ Закрытие главного окна → немедленное завершение приложения
44+
✅ Все активные уведомления закрываются автоматически
45+
✅ Процесс корректно выгружается из памяти
46+
✅ Очередь уведомлений очищается
47+
✅ Никаких ручных настроек не требуется
48+
1749
## Быстрый старт
1850

1951
### 1. Простейшее использование
@@ -27,6 +59,8 @@ ToastNotificationManager.Default.Show(
2759
"Файл успешно сохранён",
2860
ToastNotificationIcon.Success
2961
);
62+
63+
// Приложение закроется корректно даже при активных уведомлениях
3064
```
3165

3266
### 2. Использование в MVVM
@@ -140,13 +174,65 @@ var settings = new ToastNotificationSettings
140174
Width = 400, // ширина
141175
MinHeight = 80,
142176
MaxHeight = 250,
143-
PlaySound = true // системные звуки
177+
PlaySound = true, // системные звуки
178+
KeepApplicationAlive = false, // не блокировать завершение (по умолчанию)
179+
CloseOnApplicationShutdown = true // закрывать при завершении
144180
};
145181

146182
var manager = new ToastNotificationManager(settings);
147183
manager.Show("Заголовок", "Сообщение", ToastNotificationIcon.Information);
148184
```
149185

186+
### ⚠️ Управление временем жизни приложения
187+
188+
#### Стандартное поведение (рекомендуется)
189+
190+
**По умолчанию** (`KeepApplicationAlive = false`):
191+
192+
```csharp
193+
var manager = ToastNotificationManager.Default;
194+
manager.Show("Сообщение", "Текст", ToastNotificationIcon.Information);
195+
196+
// При закрытии главного окна:
197+
// ✅ Приложение завершается НЕМЕДЛЕННО
198+
// ✅ Менеджер автоматически устанавливает ShutdownMode.OnMainWindowClose
199+
// ✅ Все уведомления закрываются автоматически
200+
// ✅ Процесс выгружается из памяти
201+
```
202+
203+
#### Критические уведомления (блокируют завершение)
204+
205+
**Только для критически важных случаев** (`KeepApplicationAlive = true`):
206+
207+
```csharp
208+
var settings = new ToastNotificationSettings
209+
{
210+
KeepApplicationAlive = true, // блокировать завершение
211+
CloseOnApplicationShutdown = false, // не закрывать автоматически
212+
DisplayDuration = 0 // не закрывать по таймеру
213+
};
214+
215+
var manager = new ToastNotificationManager(settings);
216+
manager.Show(
217+
"КРИТИЧЕСКОЕ ПРЕДУПРЕЖДЕНИЕ",
218+
"Несохранённые данные будут потеряны!",
219+
ToastNotificationIcon.Critical
220+
);
221+
222+
// При этих настройках:
223+
// ⚠️ ShutdownMode НЕ изменяется
224+
// ⚠️ Приложение НЕ завершится пока есть уведомления
225+
// ⚠️ Пользователь должен вручную закрыть уведомление
226+
```
227+
228+
**Когда использовать `KeepApplicationAlive = true`:**
229+
- ❗ Критические ошибки, требующие подтверждения
230+
- ❗ Несохранённые данные перед выходом
231+
- ❗ Завершение длительных операций
232+
- ❗ Уведомления о потере данных
233+
234+
**⚠️ НЕ используйте** для обычных информационных сообщений!
235+
150236
### Изменение настроек во время работы
151237

152238
```csharp
@@ -388,6 +474,82 @@ public class FormViewModel : ViewModel
388474

389475
7. **Позиционирование** - правый нижний угол привычнее для пользователей Windows
390476

391-
## Лицензия
477+
8. **Не блокируйте завершение** - используйте `KeepApplicationAlive = false` (по умолчанию)
478+
479+
9. **Автозакрытие** - включайте `CloseOnApplicationShutdown = true` для корректной выгрузки
480+
481+
10. **Никаких ручных настроек** - менеджер автоматически настраивает ShutdownMode
482+
483+
## Устранение проблем
484+
485+
### Приложение не завершается при закрытии главного окна
486+
487+
**Симптомы:** При наличии активных уведомлений приложение остаётся в памяти после закрытия главного окна.
488+
489+
**Причина:** WPF по умолчанию использует `ShutdownMode.OnLastWindowClose`, что означает завершение при закрытии последнего окна (включая уведомления).
490+
491+
**Решение:** Система автоматически исправляет это при первом показе уведомления:
492+
493+
```csharp
494+
// Просто используйте менеджер как обычно
495+
ToastNotificationManager.Default.Show("Заголовок", "Сообщение", ToastNotificationIcon.Information);
496+
497+
// Менеджер автоматически устанавливает:
498+
// Application.Current.ShutdownMode = ShutdownMode.OnMainWindowClose;
499+
```
500+
501+
**Проверка:**
502+
```csharp
503+
// После первого показа уведомления
504+
Debug.WriteLine(Application.Current.ShutdownMode); // Должно быть: OnMainWindowClose
505+
```
506+
507+
**Если проблема сохраняется:**
508+
1. Убедитесь, что `KeepApplicationAlive = false` (по умолчанию)
509+
2. Проверьте, что используете последнюю версию библиотеки
510+
3. Убедитесь, что главное окно установлено: `Application.Current.MainWindow != null`
511+
512+
### Уведомления продолжают показываться после закрытия приложения
513+
514+
**Проблема:** Уведомления из очереди продолжают появляться после закрытия главного окна.
515+
516+
**Решение:** Система автоматически очищает очередь при завершении, но можно явно вызвать:
517+
518+
```csharp
519+
// В обработчике закрытия главного окна (необязательно)
520+
protected override void OnClosing(CancelEventArgs e)
521+
{
522+
ToastNotificationManager.Default.CloseAll();
523+
base.OnClosing(e);
524+
}
525+
```
526+
527+
### Окна уведомлений появляются в панели задач
528+
529+
**Проблема:** Иконки уведомлений видны в панели задач Windows.
530+
531+
**Решение:** Это происходит только при `KeepApplicationAlive = true`. Используйте значение по умолчанию (`false`), и окна не будут появляться в панели задач.
532+
533+
## Техническая информация
534+
535+
### Как работает автоматическая настройка
536+
537+
1. **Первый вызов `Show()`** → Вызывается `EnsureInitialized()`
538+
2. **Проверка `ShutdownMode`** → Если `OnLastWindowClose` и `KeepApplicationAlive = false`
539+
3. **Изменение режима**`Application.Current.ShutdownMode = ShutdownMode.OnMainWindowClose`
540+
4. **Подписка на события**`Application.Current.Exit += OnApplicationExit`
541+
5. **Автоматическое закрытие** → При `Exit` вызывается `CloseAll()`
542+
543+
### Совместимость
544+
545+
- ✅ .NET Framework 4.6.1 — 4.8
546+
- ✅ .NET 5, 6, 7, 8, 9, 10
547+
- ✅ Windows 7 — Windows 11
548+
- ✅ x86, x64, ARM64
549+
550+
### Производительность
392551

393-
MIT License - свободное использование в любых проектах
552+
- Ленивая инициализация (только при первом использовании)
553+
- Потокобезопасная очередь уведомлений
554+
- Минимальное влияние на UI-поток
555+
- Оптимизированное позиционирование окон

0 commit comments

Comments
 (0)