当前位置: 首页 > news >正文

c#Blazor WebAssembly在网页中多线程计算1000万次求余

在 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});}
}

三、关键实现说明

  1. 多线程创建
    使用 System.Threading.Thread 创建 3 个线程,分别处理不同起始范围的计算(0~1000 万、1000 万~2000 万、2000 万~3000 万)。

  2. 线程 ID 获取
    通过 Thread.CurrentThread.ManagedThreadId 获取托管线程 ID(Blazor WASM 中支持,可区分不同线程)。

  3. 线程安全与 UI 更新

    • 子线程不能直接更新 UI,需通过 ConcurrentQueue 存储结果(线程安全队列)。
    • 使用 Timer 定期检查队列,通过 InvokeAsync 切换到 UI 线程更新结果列表。
  4. 计算逻辑
    每个线程循环 1000 万次,统计能被 7 整除的数字个数,记录耗时和线程 ID。

四、检测方法:验证多线程执行

  1. 观察线程 ID
    运行后点击 “开始多线程计算”,会显示 3 个不同的 ThreadId(如 3、4、5),说明确实启用了多线程。

  2. 监控 CPU 使用率
    打开任务管理器(Windows)或活动监视器(Mac),计算过程中浏览器进程的 CPU 使用率会明显上升,说明多线程并行执行。

  3. 网络请求检测
    打开浏览器开发者工具(F12)的 Network 面板,整个计算过程中无任何 HTTP 请求,证明逻辑由本地 WASM 线程处理,而非服务器回调。

  4. 调试线程执行
    在 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 中执行。

http://www.xdnf.cn/news/1307629.html

相关文章:

  • MongoDB 聚合提速 3 招:$lookup 管道、部分索引、时间序列集合(含可复现实验与 explain 统计)
  • 完整设计 之 智能合约系统:主题约定、代理协议和智能合约 (临时命名)----PromptPilot (助手)答问之2
  • JavaEE 初阶第十九期:网络编程“通关记”(一)
  • 【Java学习】锁、线程死锁、线程安全2
  • 【C++】动态内存管理
  • 代码随想录Day52:图论(孤岛的总面积、沉没孤岛、水流问题、建造最大岛屿)
  • Ubuntu2204server系统安装后的初始化配置报错
  • ubuntu 20.04 安装anaconda以及安装spyder
  • GitHub PR 提交流程
  • 双向SSL认证之Apache实战配置
  • 从“Hello World”到“高并发中间件”:Go 语言 2025 系统学习路线图
  • 系统思考:情绪内耗与思维模式
  • linux服务器查看某个服务启动,运行的时间
  • DAY 46 通道注意力(SE注意力)
  • 【100页PPT】数字化转型某著名企业集团信息化顶层规划方案(附下载方式)
  • termios 线程 poll epoll进化 二叉AVL红黑树
  • 智能工厂生产监控大屏-vue纯前端静态页面练习
  • PowerShell 格式化系统完全掌握(下):自定义列/格式字符串/对齐与宽度 + 实战模板
  • System V通信机制
  • Docker之安装部署——(1)配置国内docker镜像源
  • 【Twincat3】IO的SCAN 不可选中,SCAN中后扫描不到设备
  • 代码随想录二刷之“字符串”~GO
  • 嵌入式开发学习———Linux环境下网络编程学习(二)
  • 科普:Pygame 中,`pg.Surface` v.s. `screen`
  • 电工的基础知识以及仪器的使用
  • 浏览器面试题及详细答案 88道(45-55)
  • 吉他和弦学习:从音程基石到流畅弹奏
  • 机器学习——PCA(主成分分析)降维
  • MySQL快速恢复数据的N种方案完全教程
  • JavaWeb开发_Day12