-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathScarletExitService.cs
89 lines (72 loc) · 2.63 KB
/
ScarletExitService.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
namespace MvvmScarletToolkit
{
public sealed class ScarletExitService : IExitService
{
private static readonly Lazy<ScarletExitService> _default = new Lazy<ScarletExitService>(() => new ScarletExitService(Application.Current, ScarletDispatcher.InternalDefault));
public static IExitService Default => _default.Value;
private readonly Application _app;
private readonly ScarletDispatcher _scarletDispatcher;
private readonly ConcurrentQueue<IVirtualizationViewModel> _viewModels;
private Task _shutDown = Task.CompletedTask;
public ScarletExitService(in Application app, in ScarletDispatcher dispatcher)
{
_viewModels = new ConcurrentQueue<IVirtualizationViewModel>();
_app = app ?? throw new ArgumentNullException(nameof(app));
_scarletDispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
_app.Exit += OnAppExit;
_app.SessionEnding += OnSessionEnding;
}
private void OnSessionEnding(object sender, SessionEndingCancelEventArgs e)
{
#if DEBUG
Debug.WriteLine(nameof(ScarletExitService) + "." + nameof(OnSessionEnding));
#endif
OnImmediateAppExit();
}
private void OnAppExit(object sender, ExitEventArgs e)
{
#if DEBUG
Debug.WriteLine(nameof(ScarletExitService) + "." + nameof(OnAppExit));
#endif
OnImmediateAppExit();
}
private void OnImmediateAppExit()
{
_app.Exit -= OnAppExit;
_app.SessionEnding -= OnSessionEnding;
_scarletDispatcher.SetInvokeSynchronous(true);
_shutDown = InternalShutDown();
}
private Task InternalShutDown()
{
#if DEBUG
Debug.WriteLine(nameof(ScarletExitService) + "." + nameof(InternalShutDown));
#endif
var tasks = new List<Task>(_viewModels.Count);
while (_viewModels.TryDequeue(out var viewmodel))
{
if (!viewmodel.IsLoaded)
{
continue;
}
tasks.Add(viewmodel.Unload(CancellationToken.None));
}
return Task.WhenAll(tasks);
}
public Task ShutDown()
{
return _shutDown;
}
public void UnloadOnExit(IVirtualizationViewModel viewModel)
{
_viewModels.Enqueue(viewModel);
}
}
}