You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor应用中C#向JavaScript高效传递double数组的方法

Blazor优化C#向JavaScript传递大型double数组的方法

以下是几个能有效提升传输速度的方案,根据你的场景选择合适的:

1. 用TypedArray直接共享内存,跳过序列化

普通数组传递会经过JSON序列化/反序列化,元素数量过千时这个开销会暴增。利用Blazor WebAssembly的内存直接访问特性,把C#的double数组映射成JS的Float64Array,完全绕开序列化步骤。

C#端代码:

using var arrayHandle = GCHandle.Alloc(doubleArray, GCHandleType.Pinned);
try
{
    var pointer = arrayHandle.AddrOfPinnedObject();
    await JSRuntime.InvokeVoidAsync("UpdateWithTypedArray", pointer, doubleArray.Length);
}
finally
{
    arrayHandle.Free();
}

JS端代码:

function UpdateWithTypedArray(pointer, length) {
    // 直接从C#数组的内存创建Float64Array
    const doubleArray = new Float64Array(Module.HEAPF64.buffer, pointer, length);
    // 原处理逻辑不变
    // Do some processing here
}

2. 只传变更元素,而非整个数组

如果只有部分元素(比如你测试的前四个坐标)定期更新,没必要每次传完整数组。维护变更集合,只把需要更新的索引和值传给JS,在JS侧本地数组上做增量更新。

C#端代码:

// 记录需要更新的索引和对应值
var updates = new[]
{
    new { Index = 0, Value = x1 },
    new { Index = 1, Value = y1 },
    new { Index = 2, Value = x2 },
    new { Index = 3, Value = y2 }
};
await JSRuntime.InvokeVoidAsync("UpdatePartial", updates);

JS端代码:

// 初始化时先获取一次完整数组,存在全局变量
let localDoubleArray = [];

function UpdatePartial(updates) {
    updates.forEach(item => {
        localDoubleArray[item.Index] = item.Value;
    });
    // 原处理逻辑不变
    // Do some processing here
}

这种方式传输量会大幅减少,速度提升非常明显。

3. 用ArraySegment减少内存拷贝

如果必须传递完整数组,用ArraySegment<double>替代double[],Blazor会直接传递数组的切片引用,避免创建新的数组副本,减少内存操作的开销。

C#端代码:

var segment = new ArraySegment<double>(doubleArray);
await JSRuntime.InvokeVoidAsync("Update", segment);

JS侧无需修改代码,依然可以正常接收为数组。

4. 预分配JS数组,通过内存块更新

初始化时在JS侧创建对应长度的Float64Array,后续C#端只传递更新区域的内存指针、起始索引和长度,JS直接拷贝对应内存块,彻底避免跨边界的大数据传输。

初始化步骤:
C#端:

// 告诉JS数组长度,创建对应TypedArray
await JSRuntime.InvokeVoidAsync("InitArray", doubleArray.Length);
// 第一次传递完整数组初始化
await JSRuntime.InvokeVoidAsync("Update", doubleArray);

JS端:

let sharedArray;

function InitArray(length) {
    sharedArray = new Float64Array(length);
}

function Update(doubleArray) {
    // 初始化时拷贝完整数据
    sharedArray.set(doubleArray);
}

// 后续更新用这个方法
function UpdateByMemory(pointer, startIndex, count) {
    const sourceSlice = new Float64Array(Module.HEAPF64.buffer, pointer, count);
    // 把C#中更新的部分拷贝到JS数组对应位置
    sharedArray.set(sourceSlice, startIndex);
    // 原处理逻辑不变
    // Do some processing here
}

之后C#端只需要传递更新区域的指针、起始索引和元素数量即可,效率极高。

内容的提问来源于stack exchange,提问作者gnitsuk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 15:08:14