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

如何将Span参数的Stream.Read改写为byte数组重载适配.NET Framework 4.6.1

问题背景

计划在.NET Framework 4.6.1项目中运行libvlcsharp的预览缩略图提取示例,原示例基于.NET 6编写,存在API不兼容导致的编译错误。
原示例核心处理代码如下:

private static async Task ProcessThumbnailsAsync(string destination, CancellationToken token)
{
    var frameNumber = 0;
    while (!token.IsCancellationRequested)
    {
        if (FilesToProcess.TryDequeue(out var file))
        {
            using (var image = new Image<SixLabors.ImageSharp.PixelFormats.Bgra32>((int)(Pitch / BytePerPixel), (int)Lines))
            using (var sourceStream = file.file.CreateViewStream())
            {
                var mg = image.GetPixelMemoryGroup();
                for(int i = 0; i < mg.Count; i++)
                {
                    sourceStream.Read(MemoryMarshal.AsBytes(mg[i].Span));
                }

                Console.WriteLine($"Writing {frameNumber:0000}.jpg");
                var fileName = Path.Combine(destination, $"{frameNumber:0000}.jpg");
                using (var outputFile = File.Open(fileName, FileMode.Create))
                {
                    image.Mutate(ctx => ctx.Crop((int)Width, (int)Height));
                    image.SaveAsJpeg(outputFile);
                }
            }
            file.accessor.Dispose();
            file.file.Dispose();
            frameNumber++;
        }
        else
        {
            await Task.Delay(TimeSpan.FromSeconds(1), token);
        }
    }
}

编译失败的具体代码行:

sourceStream.Read(MemoryMarshal.AsBytes(mg[i].Span));
报错原因

两个框架版本的Stream读取API存在差异:

  • .NET 6 提供Read(Span<byte>)重载,支持直接将流内容读取到Span指向的非托管/托管连续内存块
  • .NET Framework 4.x 仅提供Read(Byte[], Int32, Int32)重载,仅支持将流内容读取到字节数组中,无法直接传入Span参数
兼容修改方案

通过临时字节数组中转读取结果,再拷贝回原内存位置,完全保留原有逻辑,修改后的内存块读取循环代码如下:

var mg = image.GetPixelMemoryGroup();
for(int i = 0; i < mg.Count; i++)
{
    Span<byte> targetSpan = MemoryMarshal.AsBytes(mg[i].Span);
    // 申请和目标内存块长度匹配的临时字节数组
    byte[] tempBuffer = new byte[targetSpan.Length];
    // 调用.NET Framework 4.x支持的Read方法读取流数据
    int readCount = sourceStream.Read(tempBuffer, 0, tempBuffer.Length);
    // 将读取到的内容拷贝回原Span对应的内存位置
    tempBuffer.AsSpan(0, readCount).CopyTo(targetSpan);
}

补充说明

  • 该修改依赖System.Memory包,SixLabors.ImageSharp会自动引入该兼容包,无需额外手动安装
  • 修改后逻辑和原代码完全一致:按像素内存组的分块顺序逐块读取流数据,不会出现像素错位、内存越界问题
  • 临时字节数组随单次循环生命周期自动回收,不会造成内存泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 15:30:05