在 Blazor WebAssembly 中實現多線程計算并獲取線程 ID 是可行的,但需要正確配置多線程環境并處理線程安全和 UI 更新邏輯。以下是完整示例和檢測方法:
一、準備工作:啟用多線程支持
首先需確保項目已啟用 WebAssembly 多線程,修改項目文件(.csproj
):xml
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly"><PropertyGroup><TargetFramework>net8.0</TargetFramework><Nullable>enable</Nullable><ImplicitUsings>enable</ImplicitUsings><!-- 啟用多線程 --><WASMEnableThreads>true</WASMEnableThreads></PropertyGroup><ItemGroup><PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.0" /><PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.0" PrivateAssets="all" /></ItemGroup>
</Project>
同時,服務器需配置跨域隔離頭部(確保?SharedArrayBuffer
?可用)。如果使用?dotnet run
?調試,需在?Properties/launchSettings.json
?中添加:
"profiles": {"http": {"environmentVariables": {"ASPNETCORE_ENVIRONMENT": "Development","ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.WebAssembly.Server"},"applicationUrl": "http://localhost:5000"},"https": {"environmentVariables": {"ASPNETCORE_ENVIRONMENT": "Development","ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.WebAssembly.Server"},"applicationUrl": "https://localhost:5001;http://localhost:5000"}
}
跨域隔離頭部會由 Blazor 開發服務器自動添加,生產環境需在服務器(如 Nginx/Apache)配置?Cross-Origin-Opener-Policy: same-origin
?和?Cross-Origin-Embedder-Policy: require-corp
。
二、完整代碼實現:多線程計算示例
修改?Counter.razor
,添加多線程計算邏輯:razor
@page "/counter"
@using System.Threading
@using System.Collections.Concurrent
@inject IJSRuntime JSRuntime<PageTitle>Counter</PageTitle><h1>Counter</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button><hr /><!-- 多線程測試區域 -->
<h3>多線程計算測試</h3>
<button class="btn btn-success" @onclick="StartMultiThreadCalculation">開始多線程計算</button>
@if (results.Any())
{<div class="mt-3">@foreach (var result in results){<p>線程 ID: @result.ThreadId | 耗時: @result.ElapsedMs ms | 7的倍數個數: @result.Count</p>}</div>
}@code {private int currentCount = 0;private List<ThreadResult> results = new();// 線程安全的結果隊列(子線程寫入,主線程讀取)private ConcurrentQueue<ThreadResult> resultQueue = new();private void IncrementCount(){currentCount++;}// 線程計算結果模型private class ThreadResult{public int ThreadId { get; set; }public long ElapsedMs { get; set; }public int Count { get; set; }}// 啟動3個線程private void StartMultiThreadCalculation(){results.Clear();resultQueue.Clear();// 線程1:計算 0 ~ 999萬var thread1 = new Thread(CalculateMod7) { IsBackground = true };thread1.Start(0);// 線程2:計算 1000萬 ~ 1999萬var thread2 = new Thread(CalculateMod7) { IsBackground = true };thread2.Start(10_000_000);// 線程3:計算 2000萬 ~ 2999萬var thread3 = new Thread(CalculateMod7) { IsBackground = true };thread3.Start(20_000_000);// 啟動定時器,定期檢查結果隊列并更新UI(子線程不能直接更新UI)var timer = new Timer(_ =>{// 切換到UI線程更新InvokeAsync(() =>{while (resultQueue.TryDequeue(out var result)){results.Add(result);}StateHasChanged(); // 強制刷新UI});}, null, 0, 100); // 每100ms檢查一次}// 線程執行的計算邏輯:統計1000萬個數中i mod 7 == 0的數量private void CalculateMod7(object? startObj){if (startObj is not int start) return;int end = start + 10_000_000; // 每個線程計算1000萬次int count = 0;// 獲取當前線程ID(托管線程ID)int threadId = Thread.CurrentThread.ManagedThreadId;var stopwatch = System.Diagnostics.Stopwatch.StartNew();// 執行計算for (int i = start; i < end; i++){if (i % 7 == 0){count++;}}stopwatch.Stop();// 將結果存入線程安全隊列resultQueue.Enqueue(new ThreadResult{ThreadId = threadId,ElapsedMs = stopwatch.ElapsedMilliseconds,Count = count});}
}
三、關鍵實現說明
多線程創建:
使用?System.Threading.Thread
?創建 3 個線程,分別處理不同起始范圍的計算(0~1000 萬、1000 萬~2000 萬、2000 萬~3000 萬)。線程 ID 獲取:
通過?Thread.CurrentThread.ManagedThreadId
?獲取托管線程 ID(Blazor WASM 中支持,可區分不同線程)。線程安全與 UI 更新:
- 子線程不能直接更新 UI,需通過?
ConcurrentQueue
?存儲結果(線程安全隊列)。 - 使用?
Timer
?定期檢查隊列,通過?InvokeAsync
?切換到 UI 線程更新結果列表。
- 子線程不能直接更新 UI,需通過?
計算邏輯:
每個線程循環 1000 萬次,統計能被 7 整除的數字個數,記錄耗時和線程 ID。
四、檢測方法:驗證多線程執行
觀察線程 ID:
運行后點擊 “開始多線程計算”,會顯示 3 個不同的?ThreadId
(如 3、4、5),說明確實啟用了多線程。監控 CPU 使用率:
打開任務管理器(Windows)或活動監視器(Mac),計算過程中瀏覽器進程的 CPU 使用率會明顯上升,說明多線程并行執行。網絡請求檢測:
打開瀏覽器開發者工具(F12)的?Network?面板,整個計算過程中無任何 HTTP 請求,證明邏輯由本地 WASM 線程處理,而非服務器回調。調試線程執行:
在?CalculateMod7
?方法中設置斷點(需在瀏覽器開發者工具的?Sources?面板中找到對應代碼),調試時可看到斷點在不同線程中觸發。
五、運行結果示例
點擊 “開始多線程計算” 后,會顯示類似結果:plaintext
線程 ID: 3 | 耗時: 235 ms | 7的倍數個數: 1428572
線程 ID: 4 | 耗時: 241 ms | 7的倍數個數: 1428571
線程 ID: 5 | 耗時: 239 ms | 7的倍數個數: 1428571
- 不同的?
ThreadId
?證明多線程生效。 - 耗時相近說明線程并行執行(總耗時約等于單線程耗時,而非 3 倍)。
總結
Blazor WebAssembly 中的多線程計算完全在客戶端通過 WASM 執行,無 HTTP 回調。通過?Thread
?類創建線程,ManagedThreadId
?獲取線程 ID,配合線程安全隊列和 UI 線程切換,可實現多線程任務并正確顯示結果。網絡監控和線程 ID 驗證可證明邏輯在本地 WASM 中執行。