@@ -27,11 +27,26 @@ namespace Flow.Launcher
2727{
2828 public partial class App : IDisposable , ISingleInstanceApp
2929 {
30+ #region Public Properties
31+
3032 public static IPublicAPI API { get ; private set ; }
31- private const string Unique = "Flow.Launcher_Unique_Application_Mutex" ;
33+
34+ #endregion
35+
36+ #region Private Fields
37+
3238 private static bool _disposed ;
39+ private MainWindow _mainWindow ;
40+ private readonly MainViewModel _mainVM ;
3341 private readonly Settings _settings ;
3442
43+ // To prevent two disposals running at the same time.
44+ private static readonly object _disposingLock = new ( ) ;
45+
46+ #endregion
47+
48+ #region Constructor
49+
3550 public App ( )
3651 {
3752 // Initialize settings
@@ -79,34 +94,44 @@ public App()
7994 {
8095 API = Ioc . Default . GetRequiredService < IPublicAPI > ( ) ;
8196 _settings . Initialize ( ) ;
97+ _mainVM = Ioc . Default . GetRequiredService < MainViewModel > ( ) ;
8298 }
8399 catch ( Exception e )
84100 {
85101 ShowErrorMsgBoxAndFailFast ( "Cannot initialize api and settings, please open new issue in Flow.Launcher" , e ) ;
86102 return ;
87103 }
88- }
89104
90- private static void ShowErrorMsgBoxAndFailFast ( string message , Exception e )
91- {
92- // Firstly show users the message
93- MessageBox . Show ( e . ToString ( ) , message , MessageBoxButton . OK , MessageBoxImage . Error ) ;
105+ // Local function
106+ static void ShowErrorMsgBoxAndFailFast ( string message , Exception e )
107+ {
108+ // Firstly show users the message
109+ MessageBox . Show ( e . ToString ( ) , message , MessageBoxButton . OK , MessageBoxImage . Error ) ;
94110
95- // Flow cannot construct its App instance, so ensure Flow crashes w/ the exception info.
96- Environment . FailFast ( message , e ) ;
111+ // Flow cannot construct its App instance, so ensure Flow crashes w/ the exception info.
112+ Environment . FailFast ( message , e ) ;
113+ }
97114 }
98115
116+ #endregion
117+
118+ #region Main
119+
99120 [ STAThread ]
100121 public static void Main ( )
101122 {
102- if ( SingleInstance < App > . InitializeAsFirstInstance ( Unique ) )
123+ if ( SingleInstance < App > . InitializeAsFirstInstance ( ) )
103124 {
104125 using var application = new App ( ) ;
105126 application . InitializeComponent ( ) ;
106127 application . Run ( ) ;
107128 }
108129 }
109130
131+ #endregion
132+
133+ #region App Events
134+
110135#pragma warning disable VSTHRD100 // Avoid async void methods
111136
112137 private async void OnStartup ( object sender , StartupEventArgs e )
@@ -142,11 +167,11 @@ await Stopwatch.NormalAsync("|App.OnStartup|Startup cost", async () =>
142167
143168 await imageLoadertask ;
144169
145- var window = new MainWindow ( ) ;
170+ _mainWindow = new MainWindow ( ) ;
146171
147172 Log . Info ( $ "|App.OnStartup|Dependencies Info:{ ErrorReporting . DependenciesInfo ( ) } ") ;
148173
149- Current . MainWindow = window ;
174+ Current . MainWindow = _mainWindow ;
150175 Current . MainWindow . Title = Constant . FlowLauncher ;
151176
152177 HotKeyMapper . Initialize ( ) ;
@@ -163,8 +188,7 @@ await Stopwatch.NormalAsync("|App.OnStartup|Startup cost", async () =>
163188 AutoUpdates ( ) ;
164189
165190 API . SaveAppAllSettings ( ) ;
166- Log . Info (
167- "|App.OnStartup|End Flow Launcher startup ---------------------------------------------------- " ) ;
191+ Log . Info ( "|App.OnStartup|End Flow Launcher startup ----------------------------------------------------" ) ;
168192 } ) ;
169193 }
170194
@@ -197,7 +221,6 @@ private void AutoStartup()
197221 }
198222 }
199223
200- //[Conditional("RELEASE")]
201224 private void AutoUpdates ( )
202225 {
203226 _ = Task . Run ( async ( ) =>
@@ -215,11 +238,29 @@ private void AutoUpdates()
215238 } ) ;
216239 }
217240
241+ #endregion
242+
243+ #region Register Events
244+
218245 private void RegisterExitEvents ( )
219246 {
220- AppDomain . CurrentDomain . ProcessExit += ( s , e ) => Dispose ( ) ;
221- Current . Exit += ( s , e ) => Dispose ( ) ;
222- Current . SessionEnding += ( s , e ) => Dispose ( ) ;
247+ AppDomain . CurrentDomain . ProcessExit += ( s , e ) =>
248+ {
249+ Log . Info ( "|App.RegisterExitEvents|Process Exit" ) ;
250+ Dispose ( ) ;
251+ } ;
252+
253+ Current . Exit += ( s , e ) =>
254+ {
255+ Log . Info ( "|App.RegisterExitEvents|Application Exit" ) ;
256+ Dispose ( ) ;
257+ } ;
258+
259+ Current . SessionEnding += ( s , e ) =>
260+ {
261+ Log . Info ( "|App.RegisterExitEvents|Session Ending" ) ;
262+ Dispose ( ) ;
263+ } ;
223264 }
224265
225266 /// <summary>
@@ -240,20 +281,60 @@ private static void RegisterAppDomainExceptions()
240281 AppDomain . CurrentDomain . UnhandledException += ErrorReporting . UnhandledExceptionHandle ;
241282 }
242283
243- public void Dispose ( )
284+ #endregion
285+
286+ #region IDisposable
287+
288+ protected virtual void Dispose ( bool disposing )
244289 {
245- // if sessionending is called, exit proverbially be called when log off / shutdown
246- // but if sessionending is not called, exit won't be called when log off / shutdown
247- if ( ! _disposed )
290+ // Prevent two disposes at the same time.
291+ lock ( _disposingLock )
248292 {
249- API . SaveAppAllSettings ( ) ;
293+ if ( ! disposing )
294+ {
295+ return ;
296+ }
297+
298+ if ( _disposed )
299+ {
300+ return ;
301+ }
302+
250303 _disposed = true ;
251304 }
305+
306+ Stopwatch . Normal ( "|App.Dispose|Dispose cost" , ( ) =>
307+ {
308+ Log . Info ( "|App.Dispose|Begin Flow Launcher dispose ----------------------------------------------------" ) ;
309+
310+ if ( disposing )
311+ {
312+ // Dispose needs to be called on the main Windows thread,
313+ // since some resources owned by the thread need to be disposed.
314+ _mainWindow ? . Dispatcher . Invoke ( _mainWindow . Dispose ) ;
315+ _mainVM ? . Dispose ( ) ;
316+ }
317+
318+ Log . Info ( "|App.Dispose|End Flow Launcher dispose ----------------------------------------------------" ) ;
319+ } ) ;
252320 }
253321
322+ public void Dispose ( )
323+ {
324+ // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
325+ Dispose ( disposing : true ) ;
326+ GC . SuppressFinalize ( this ) ;
327+ }
328+
329+ #endregion
330+
331+ #region ISingleInstanceApp
332+
254333 public void OnSecondAppStarted ( )
255334 {
256335 Ioc . Default . GetRequiredService < MainViewModel > ( ) . Show ( ) ;
257336 }
337+
338+ #endregion
258339 }
259340}
0 commit comments