起動シーケンス¶
この節の要旨 起動時間は約 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 | — | — |

計測点は [STARTUP-TIMING] / [CTOR-TIMING] / [APPLY-TIMING] / [LOADED-TIMING] のログプレフィックスで出力されます(data/logs/*.log)。
非同期チェーンとサービス遅延初期化¶
起動時は、以下の順に実行されます。
- OnStartup(UI): 最小限の同期処理のみ(FileLogger・設定読込 await・テーマ適用・L10n・リソース辞書)。
- MainWindow 表示:
InitializeComponent+ApplySettings+ ナビペイン初期化を UI で。 Application.Current.Dispatcher.BeginInvoke(..., DispatcherPriority.Background): レンダリング完了後の低優先度キューでCpuIdleService/TrayIconService/UpdateServiceを初期化。StartupInitTask = Task.Run(...)(バックグラウンドスレッド):PathHelper.EnsureSpecialFoldersCached→Database.InitializeAsync→License.InitializeAsync+TabActivity.InitializeAsyncを直列/並列実行。Window_Loadedの非同期処理でawait StartupInitTaskして合流。--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)。