The Lifecycle Service (ILifecycleService) is a workbench service that manages the application lifecycle, including startup phases, shutdown events, and window lifecycle. It allows components to participate in startup sequencing and handle shutdown gracefully.
The Lifecycle Service is defined in src/vs/workbench/services/lifecycle/common/lifecycle.ts:10 and coordinates the various phases of the application lifecycle.
VS Code goes through several phases during startup:
LifecyclePhase Enum
Copy
Ask AI
export const enum LifecyclePhase { /** * Starting phase - getting ready * Note: Blocks editor from showing to the user */ Starting = 1, /** * Ready phase - services are ready, about to restore UI * Note: Blocks editor from showing to the user */ Ready = 2, /** * Restored phase - views, panels, editors have restored * Editors are given time to restore their contents */ Restored = 3, /** * Eventually phase - everything is loaded and settled * Occurs 2-5 seconds after Restored */ Eventually = 4}
// Wait for a specific phaseawait lifecycleService.when(LifecyclePhase.Ready);console.log('Services are ready');await lifecycleService.when(LifecyclePhase.Restored);console.log('UI is restored');await lifecycleService.when(LifecyclePhase.Eventually);console.log('Everything is loaded');// Use in async initializationexport class LazyService { constructor( @ILifecycleService private lifecycleService: ILifecycleService ) {} async whenReady(): Promise<void> { await this.lifecycleService.when(LifecyclePhase.Restored); // Perform initialization that should happen after UI is restored }}
Work performed in Starting and Ready phases blocks the editor from showing to the user. Prefer doing work in Restored or Eventually phases when possible.
import { StartupKind, StartupKindToString } from 'vs/workbench/services/lifecycle/common/lifecycle';const startupKind = lifecycleService.startupKind;switch (startupKind) { case StartupKind.NewWindow: console.log('Freshly opened window'); break; case StartupKind.ReloadedWindow: console.log('Window was reloaded'); break; case StartupKind.ReopenedWindow: console.log('Window was reopened (e.g., after restart)'); break;}console.log('Startup:', StartupKindToString(startupKind));
lifecycleService.onShutdownVeto(() => { console.log('Shutdown was vetoed by a component'); // Update UI or state to reflect that shutdown was cancelled});
import { BeforeShutdownErrorEvent } from 'vs/workbench/services/lifecycle/common/lifecycle';lifecycleService.onBeforeShutdownError((event: BeforeShutdownErrorEvent) => { console.error('Error during shutdown veto handling:', event.error); console.log('Shutdown reason was:', event.reason); // Shutdown will be cancelled due to the error});
Force shutdown even if join operations haven’t completed
WillShutdownJoinerOrder
Copy
Ask AI
export enum WillShutdownJoinerOrder { /** * Default order - services are still functional * Use this for most cases */ Default = 1, /** * Last order - services may be disposed * Only use when you have no service dependencies */ Last}
// Check if shutdown is in progressif (lifecycleService.willShutdown) { console.log('Shutdown is in progress'); // Don't start new long-running operations}
Normally you should not call shutdown() directly. Use IHostService.close() or INativeHostService.quit() instead to properly close windows or quit the application.
export class ReloadHandler { constructor( @ILifecycleService private lifecycleService: ILifecycleService ) { this.handleReload(); } private handleReload(): void { // Detect reload on startup if (this.lifecycleService.startupKind === StartupKind.ReloadedWindow) { this.restoreAfterReload(); } // Save state before reload this.lifecycleService.onWillShutdown(event => { if (event.reason === ShutdownReason.RELOAD) { event.join( this.saveStateForReload(), { id: 'reloadHandler.save', label: 'Saving state for reload' } ); } }); } private restoreAfterReload(): void { console.log('Restoring state after reload'); // Restore saved state } private async saveStateForReload(): Promise<void> { console.log('Saving state before reload'); // Save state that should survive reload }}