# 画面設計書 3-Wasm Browser Threading Sample

## 概要

本ドキュメントは、.NET WebAssembly のマルチスレッドサンプル画面「Wasm Browser Threading Sample」の設計内容を記載した画面設計書です。本画面は .NET Runtime リポジトリにおける WebAssembly のマルチスレッド機能をデモンストレーションするサンプルアプリケーションです。

### 本画面の処理概要

本画面は、ブラウザ上で .NET WebAssembly ランタイムのマルチスレッド機能を使用して、バックグラウンドスレッドで長時間計算（フィボナッチ数列計算）を実行し、その進捗状況をメインスレッドから UI に表示するサンプルアプリケーションです。

**業務上の目的・背景**：本画面は、WebAssembly でのマルチスレッド処理の実装方法を開発者に示すことを目的としています。従来のシングルスレッド WebAssembly では UI がブロックされる長時間計算も、マルチスレッドを活用することでメインスレッドを解放し、ユーザー体験を向上させることができます。本サンプルでは、ワーカースレッドでの計算実行、スレッド間通信、進捗表示の更新方法、ガベージコレクションとの連携などの実践的なパターンを学ぶことができます。

**画面へのアクセス方法**：ローカル開発サーバー（通常は `http://localhost:8000/`）にブラウザでアクセスすることで画面を表示できます。マルチスレッド機能には `crossOriginIsolated` が必要なため、適切な HTTP ヘッダー（COOP/COEP）の設定が必要です。

**主要な操作・処理内容**：
1. 画面ロード時に JavaScript（main.js）が .NET WebAssembly ランタイムを初期化
2. 自動的にフィボナッチ計算（N=29）がバックグラウンドスレッドで開始
3. メインスレッドから定期的に進捗状況（サイコロアニメーション）をポーリング
4. 計算完了後、結果を DOM に表示
5. N の値を変更可能な入力フィールドが有効化
6. ユーザーが N の値を変更すると再計算を実行

**画面遷移**：本画面は単一画面のサンプルアプリケーションであり、他画面への遷移はありません。

**権限による表示制御**：本画面は認証・認可機能を持たないデモアプリケーションであり、権限による表示制御はありません。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | Mono | 主機能 | WebAssembly ランタイム上でマルチスレッド処理を実行 |
| 20 | System.Threading | 主機能 | スレッド処理と同期プリミティブを使用した長時間計算 |
| 59 | WebAssembly Workload | 主機能 | WebAssembly アプリケーションのビルドと実行をサポート |
| 5 | ガベージコレクター | 補助機能 | スレッド内でのメモリ管理と GC コレクション |

## 画面種別

インタラクティブデモ画面（単一画面）

## URL/ルーティング

- ローカル開発: `http://localhost:8000/index.html`
- 静的ファイルパス: `src/mono/sample/wasm/browser-threads/wwwroot/index.html`

## 入出力項目

| 項目名 | 入出力 | データ型 | 説明 |
|--------|--------|----------|------|
| inputN | 入力 | number | フィボナッチ計算の N 値（初期値: 29） |

## 表示項目

| 項目ID | 項目名 | 要素タイプ | 説明 |
|--------|--------|-----------|------|
| header | 画面タイトル | h3 | 「Wasm Browser Threading Sample」と表示 |
| inputN | N 入力 | input[type=number] | フィボナッチ計算の N 値を入力 |
| out | 計算結果 | span | 計算結果 Fib(N) の値を表示 |
| progressElement | 進捗表示 | span | サイコロアニメーションで進捗を表示（font-size: 500%） |

## イベント仕様

### 1-画面ロード完了イベント

画面がロードされると、以下の処理が自動的に実行されます:

1. `main.js` がモジュールとして読み込まれる
2. `dotnet.create()` で WebAssembly ランタイムを初期化
3. `jsThreadBlockingMode: "WarnWhenBlockingWait"` でブロッキング警告を有効化
4. `setModuleImports` で JavaScript 関数を C# から呼び出せるように登録
5. `getAssemblyExports` で C# の公開メソッドを取得
6. `doSlowMath()` でフィボナッチ計算を開始
7. 50ms 間隔でポーリングし進捗を更新
8. 計算完了後、入力フィールドを有効化

### 2-N 値変更イベント

ユーザーが N の値を変更すると:

1. `onInputValueChanged` が呼び出される
2. 入力フィールドが無効化される
3. `doSlowMath()` で新しい N 値でフィボナッチ計算を再実行
4. 計算完了後、入力フィールドを再度有効化

## データベース更新仕様

### 操作別データベース影響一覧

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| - | - | - | 本画面はデータベースを使用しません |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|---------|
| MSG-001 | 情報 | Hello, World! | Main メソッド実行時にコンソール出力 |
| MSG-002 | 情報 | Progress2 A {cwd} | Progress2 メソッド内でディレクトリ取得時 |
| MSG-003 | 情報 | Progress2 B | Progress2 メソッドの Task.Wait() 完了後 |
| MSG-004 | 表示 | Fib({N}) = {result} | 計算完了時に DOM に表示 |
| MSG-005 | 進捗 | サイコロ絵文字（1-6） | 計算中の進捗表示 |

## 例外処理

| 例外種別 | 発生条件 | 対応処理 |
|---------|---------|---------|
| JavaScript エラー | WebAssembly ランタイム初期化失敗時 | `exit(2, err)` を呼び出してエラーコード2で終了 |
| ブロッキング警告 | UI スレッドでブロッキング Wait 実行時 | コンソールに警告出力（jsThreadBlockingMode 設定） |

## 備考

- `crossOriginIsolated: true` がマルチスレッド動作に必須（SharedArrayBuffer のため）
- `jsThreadBlockingMode: "WarnWhenBlockingWait"` でブロッキング待機時に警告
- サイコロ絵文字（Unicode: U+2680-U+2685）で視覚的な進捗表示
- `Task.Run()` でバックグラウンドスレッドを使用
- 1000 回ごとにガベージを生成、500000 回ごとに GC.Collect() を実行

---

## コードリーディングガイド

本画面を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、スレッド間で受け渡されるデータと状態管理を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Program.cs | `src/mono/sample/wasm/browser-threads/Program.cs` | 静的フィールドによる状態管理と JSImport/JSExport 定義を確認 |

**読解のコツ**: `_isRunning` フラグでスレッド間の状態を共有しています。`_animations` 配列はサイコロ絵文字のローテーション用です。

#### Step 2: エントリーポイントを理解する

処理の起点となるファイル・関数を特定します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.html | `src/mono/sample/wasm/browser-threads/wwwroot/index.html` | HTML 構造と入力フィールドを確認 |
| 2-2 | main.js | `src/mono/sample/wasm/browser-threads/wwwroot/main.js` | スレッド管理とポーリング処理を確認 |

**主要処理フロー (main.js)**:
1. **11-23行目**: `dotnet.create()` でランタイム初期化、`jsThreadBlockingMode` 設定
2. **25-32行目**: `setModuleImports` で updateProgress, updateProgress2 を公開
3. **36-38行目**: `doSlowMath()` 呼び出し後、入力フィールド有効化
4. **47-60行目**: `doSlowMath` - フィボナッチ計算と 50ms ポーリング
5. **62-68行目**: `updateProgress` - DOM の進捗表示を更新
6. **70-72行目**: `updateProgress2` - C# の Progress2 を呼び出し

#### Step 3: C# 側のマルチスレッド処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Program.cs | `src/mono/sample/wasm/browser-threads/Program.cs` | Task.Run によるバックグラウンド処理とスレッド間通信を確認 |

**主要処理フロー (Program.cs)**:
- **16-20行目**: 静的フィールド - `_animationCounter`, `_isRunning`, `_animations`
- **22-28行目**: `Main` - Timer スレッド生成とコンソール出力
- **39-53行目**: `Progress2` - 同期的な POSIX 呼び出しとブロッキング待機のテスト
- **55-64行目**: `Progress` - JSExport で進捗アニメーションを更新
- **66-76行目**: `Fib` - Task.Run でバックグラウンドスレッドで計算
- **78-93行目**: `FibImpl` - 再帰的フィボナッチ計算とガベージ生成

### プログラム呼び出し階層図

```
[Browser] index.html 読み込み
    |
    +-- [JavaScript] main.js 実行
            |
            +-- dotnet.create() - WebAssembly ランタイム初期化
            |       |
            |       +-- jsThreadBlockingMode: "WarnWhenBlockingWait"
            |
            +-- setModuleImports() - updateProgress, updateProgress2 を公開
            |
            +-- getAssemblyExports() - C# メソッドを取得
            |
            +-- doSlowMath() 開始
                    |
                    +-- exports.Sample.Test.Fib(N)
                    |       |
                    |       +-- [C#/Background Thread] FibImpl(N)
                    |               |
                    |               +-- 再帰的フィボナッチ計算
                    |               +-- AllocateGarbage() (1000回ごと)
                    |               +-- GC.Collect() (500000回ごと)
                    |
                    +-- ポーリングループ (50ms間隔)
                            |
                            +-- exports.Sample.Test.Progress()
                                    |
                                    +-- [C#] Progress()
                                            |
                                            +-- [JavaScript] updateProgress(サイコロ)
                                                    |
                                                    +-- DOM 更新 (progressElement)
```

### データフロー図

```
[入力]                      [処理]                           [出力]

inputN.value ---------> doSlowMath()
  (N=29)                    |
                            v
                    +-- Fib(N) [Background Thread] --+
                    |   Task.Run(() => FibImpl(N))   |
                    +---------------+----------------+
                                    |
                                    | (非同期)
                                    v
                            FibImpl(N) 再帰計算
                                    |
                    +---------------+----------------+
                    |                                |
                    v                                v
            _callCounter % 1000 == 0        _callCounter % 500000 == 0
                    |                                |
                    v                                v
            AllocateGarbage()                  GC.Collect()
                    |
                    +--------------------------------+
                                    |
                                    v
                            計算完了 (Promise 解決)
                                    |
                                    v
                    document.getElementById("out")
                        .innerText = "Fib(29) = 514229"

[並行処理]

ポーリングループ (50ms間隔)
    |
    v
Progress() ---------> _animations[_animationCounter++]
    |                        |
    v                        v
updateProgress() -----> progressElement.innerText = "サイコロ"
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.html | `src/mono/sample/wasm/browser-threads/wwwroot/index.html` | テンプレート | HTML エントリーポイント、入力フィールド定義 |
| main.js | `src/mono/sample/wasm/browser-threads/wwwroot/main.js` | ソース | JavaScript エントリーポイント、ポーリング処理 |
| Program.cs | `src/mono/sample/wasm/browser-threads/Program.cs` | ソース | C# メインロジック、マルチスレッド処理、フィボナッチ計算 |
| dotnet.js | `_framework/dotnet.js` | ランタイム | .NET WebAssembly ランタイムローダー（ビルド時生成） |
