コンテンツにスキップ

起動シーケンス

この節の要旨 起動時間は約 1.3 秒(操作可能まで)を目標に制御。重い処理はすべて非同期 + 劣後(Background 優先度の Dispatcher.BeginInvoke もしくは StartupInitTask のスレッドプール実行)に追い出し、UI スレッドは XAML パースと設定適用のみに集中させます。

初回起動時はウェルカムウィンドウが表示され、機能紹介・テーマ選択・EULA 同意を経てメインウィンドウへ遷移します。

2回目以降はメインウィンドウが直接表示され、ステータスバーに短いウェルカムアニメーション(約3.5秒)が流れます(演出設定でオフにすると即表示)。

サービス(タスクトレイ・自動更新等)はレンダリング完了後に遅延初期化されるため、起動直後の画面表示がスムーズです。 - 二つ名ウェルカムグリーティング: 起動時にチャレンジで獲得した二つ名がステータスバーにウェルカムメッセージとして表示されます。

フェーズ構成と実測値(v0.40.31 以降のベースライン)

フェーズ 所要時間目安 実行スレッド 主な処理
OnStartup 〜150ms UI Mutex、FileLogger、AppResources.xaml(LoadHeavyResources)、テーマ適用、KeyBindings、L10n
MainWindow ctor 〜730ms(起動からの累積では〜880ms) UI InitializeComponent(XAML パース)、NavViews 初期化、ApplySettings(テーマ・AI 設定ロード)
Window_Loaded → InitializeAsync 〜435ms UI + 非同期 StartupInitTask 待機、ペインのタブ復元、お気に入り読込
合計(操作可能まで) 約 1,300ms — —

起動の 3 フェーズの内訳。OnStartup 150 ms と MainWindow の構築 732 ms が UI スレッド、Loaded から初期化までの 435 ms が UI と非同期で、合わせて約 1,300 ms で操作可能になる

計測点は [STARTUP-TIMING] / [CTOR-TIMING] / [APPLY-TIMING] / [LOADED-TIMING] のログプレフィックスで出力されます(data/logs/*.log)。

非同期チェーンとサービス遅延初期化

起動時は、以下の順に実行されます。

  1. OnStartup(UI): 最小限の同期処理のみ(FileLogger・設定読込 await・テーマ適用・L10n・リソース辞書)。
  2. MainWindow 表示: InitializeComponent + ApplySettings + ナビペイン初期化を UI で。
  3. Application.Current.Dispatcher.BeginInvoke(..., DispatcherPriority.Background): レンダリング完了後の低優先度キューで CpuIdleService / TrayIconService / UpdateService を初期化。
  4. StartupInitTask = Task.Run(...)(バックグラウンドスレッド): PathHelper.EnsureSpecialFoldersCached → Database.InitializeAsync → License.InitializeAsync + TabActivity.InitializeAsync を直列/並列実行。Window_Loaded の非同期処理で await StartupInitTask して合流。
  5. --updated 引数検知: 付いて起動した場合は「アップデートが完了しました(vX.Y.Z)」トースト通知と UpdateService.CleanupTempFiles() を実行。

起動パスの禁則事項(CLAUDE.md 準拠)

  • UI スレッドから App.AiService に触れない。Lazy<AiService> のロック競合で起動がフリーズした実績がある(feedback_lazy_aiservice_no_ui_thread)。必要な場合は Task.Run 経由で初回アクセスを強制。
  • OnStartup 内で同期 I/O を増やさない(File.ReadAllText, Directory.CreateDirectory, 大量ディスクアクセスなど)。同期 I/O を追加する場合は StartupInitTask に逃がす。
  • Dispatcher.BeginInvoke(Background) の中で重い同期処理を行わない。Background 優先度は UI スレッドを実質ブロックする。
  • 新しい Lazy<T> サービスを起動パスで初回アクセスしない。初回アクセスのコストが UI スレッドに乗る。
  • bin/ を削除しない(実行データが含まれるため)。XAML キャッシュクリアは obj/ のみ。

起動関連コードの変更は専用の guard-startup エージェント経由で実施するルール(CLAUDE.md「8. 起動処理の変更」)。

既知の起動時挙動

  • PaneCount=1 + 画面外退避での DWM フリーズ: Windows Update 後の環境で ContentRendered が発火しないケースがあり、起動時に一度 PaneCount=2 で仮描画してから ContentRendered 後に設定値へ切り替える(project_panecount1_dwm_freeze)。