using System; using System.Threading; using System.Threading.Tasks; namespace PCL.Core.App.IoC; partial class Lifecycle { /// /// 生命周期状态改变时触发的事件。
/// 非异步执行,请注意自行实现必要的异步,否则会卡住生命周期管理线程。 ///
public static event Action? StateChanged; /// /// 当前的生命周期状态,会随生命周期变化随时更新。 /// public static LifecycleState CurrentState { get; private set { Context.Debug($"状态改变: {value}"); field = value; try { StateChanged?.Invoke(value); } catch (Exception ex) { Context.Warn("状态更改事件出错", ex); } } } = LifecycleState.BeforeLoading; private static void _NextState(LifecycleState? enforce = null) { if (enforce is { } state) CurrentState = state; else CurrentState++; } /// /// 阻塞当前线程并等待到达指定生命周期状态。 /// /// 指定生命周期状态 /// /// 是否真正“等待”过(若调用该方法时已经到达或晚于指定状态,则为 false) /// public static bool WaitForState(LifecycleState state) { if (CurrentState >= state) return false; // 如果已经是目标状态,直接返回 using var mre = new ManualResetEventSlim(false); StateChanged += TempHandler; try { mre.Wait(); } // 等待 Set() 方法 finally { StateChanged -= TempHandler; } // 取消订阅,避免内存泄漏或重复唤醒 return true; void TempHandler(LifecycleState s) { // ReSharper disable once AccessToDisposedClosure if (s == state) mre.Set(); } } /// /// 异步等待到达指定生命周期状态。 /// /// 指定生命周期状态 /// /// 结果表示是否真正“等待”过的 实例(若调用该方法时已经到达或晚于指定状态,则结果为 false) /// public static Task WaitForStateAsync(LifecycleState state) { if (CurrentState >= state) return Task.FromResult(false); // 如果已经是目标状态,则直接返回 false var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); StateChanged += TempHandler; return tcs.Task; void TempHandler(LifecycleState s) { if (s != state) return; StateChanged -= TempHandler; tcs.TrySetResult(true); } } /// /// 快速注册改变到目标生命周期状态的事件,与直接注册 的区别是会自动判断目标状态并自动移除事件注册。 /// /// 目标生命周期状态 /// 事件触发委托 public static void When(LifecycleState when, Action action) { if (CurrentState >= when) return; StateChanged += TempHandler; return; void TempHandler(LifecycleState state) { if (state != when) return; action(); StateChanged -= TempHandler; } } } /// /// 生命周期状态 /// public enum LifecycleState { /// /// 手动运行
/// 表示不应由生命周期管理自动运行。拥有该状态的服务项可以使用 /// 和 手动控制启动和停止。
/// 非异步启动可能在任意线程执行。 ///
Manual, /// /// 预加载
/// 一些提前运行的无需使用基本组件的事件,如检测单例、提权进程、更新等。 /// 在该状态运行的服务可以使用 请求直接退出程序。
/// 非异步启动将在 STA 线程执行。 ///
BeforeLoading, /// /// 加载
/// 基本组件初始化,如日志、系统基本信息、设置项等。
/// 非异步启动将在 STA 线程执行。 ///
Loading, /// /// 加载结束
/// 非基本组件初始化,大多数功能性组件如 RPC 服务端、Yggdrasil 服务端的初始化等,均应在此时运行。
/// 非异步启动将在 STA 线程执行,不建议在此状态非异步启动。 ///
Loaded, /// /// 窗口创建
/// 主窗体内容初始化,正常情况下不应有任何与主窗体初始化无关的事件在此时运行。
/// 非异步启动将在 STA 线程执行。 ///
WindowCreating, /// /// 窗口创建结束
/// 一些事件需要依赖已经加载完成的窗体,如初始弹窗提示、主题刷新等,应在此时运行。
/// 非异步启动将在 STA 线程执行,耗时操作可能导致主窗体卡顿。 ///
WindowCreated, /// /// 正在运行
/// 程序开始正常运行后的工作,如检查更新。
/// 非异步启动将在新的工作线程执行。 ///
Running, /// /// 尝试关闭程序
/// 可能有服务需要阻止启动器退出?类似 WPF 窗体的 Closing 事件,但启动器应该没这需求吧...
/// 非异步启动将在 STA 线程执行,耗时操作可能导致主窗体卡顿。 ///
Closing, /// /// 关闭程序
/// 确认关闭程序后开始执行关闭流程,一些需要保存状态的服务项应在此时运行。 /// 生命周期管理会在此时自动执行所有托管的未停止服务项的 Stop 方法,因此托管的服务项无需额外关注该状态。
/// 非异步启动可能在任意线程执行,耗时操作可能导致主窗体卡顿。 ///
Exiting, }