qidao123.com技术社区-IT企服评测·应用市场

标题: 【C#】Buffer.BlockCopy的使用 [打印本页]

作者: 万万哇    时间: 2025-5-7 00:03
标题: 【C#】Buffer.BlockCopy的使用
Buffer.BlockCopy 是 C# 中的一个方法,用于在数组之间高效地复制字节块。它紧张用于操作字节数组(byte[]),但也可以用于其他类型的数组,由于它直接基于内存操作。
以下是关于 Buffer.BlockCopy 的详细分析和使用示例:
语法


  1. public static void BlockCopy(
  2.     Array src,         // 源数组
  3.     int srcOffset,     // 源数组中的起始位置(以字节为单位)
  4.     Array dst,         // 目标数组
  5.     int dstOffset,     // 目标数组中的起始位置(以字节为单位)
  6.     int count          // 要复制的字节数
  7. );
复制代码
注意事项

 
示例 1: 从一个 byte[] 复制到另一个 byte[]
  1. byte[] source = { 1, 2, 3, 4, 5 };
  2. byte[] destination = new byte[5];
  3. // 将 source 的前 3 个字节复制到 destination 的第 1 个位置
  4. Buffer.BlockCopy(source, 0, destination, 1, 3);
  5. Console.WriteLine(string.Join(", ", destination));
  6. // 输出: 0, 1, 2, 3, 0
复制代码
示例 2: 从 int[] 复制到 byte[]
  1. int[] source = { 1, 2, 3 }; // 每个 int 占 4 字节
  2. byte[] destination = new byte[12]; // 3 个 int 需要 12 字节
  3. // 将 source 的所有字节复制到 destination
  4. Buffer.BlockCopy(source, 0, destination, 0, 12);
  5. Console.WriteLine(string.Join(", ", destination));
  6. // 输出: 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0
复制代码
示例 3: 从 float[] 复制到 byte[]
  1. float[] source = { 1.0f, 2.0f, 3.0f }; // 每个 float 占 4 字节
  2. byte[] destination = new byte[12]; // 3 个 float 需要 12 字节
  3. // 将 source 的所有字节复制到 destination
  4. Buffer.BlockCopy(source, 0, destination, 0, 12);
  5. Console.WriteLine(string.Join(", ", destination));
  6. // 输出: 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64
复制代码
示例 4: 部分复制
  1. byte[] source = { 1, 2, 3, 4, 5 };
  2. byte[] destination = new byte[5];
  3. // 从 source 的第 2 个字节开始复制 2 个字节到 destination 的第 1 个位置
  4. Buffer.BlockCopy(source, 2, destination, 1, 2);
  5. Console.WriteLine(string.Join(", ", destination));
  6. // 输出: 0, 3, 4, 0, 0
复制代码
常见用途

与其他方法的对比

方法特点Array.Copy支持不同类型的数组,但按元素复制,不得当跨类型操作。Buffer.BlockCopy按字节复制,得当底层操作,性能更高,但只能用于一维数组。MemoryStream更高级别的流操作,支持动态扩展,但性能不如 Buffer.BlockCopy。  
Buffer.BlockCopy 的线程安全性

Buffer.BlockCopy 本身是一个静态方法,它不会直接管理线程安全题目。是否支持多线程操作取决于你如何使用它以及目标数组和源数组的访问方式。
分析 Buffer.BlockCopy线程安全性

多线程使用的注意事项

场景 1: 每个线程操作独立的数组
如果每个线程操作的是完全独立的数组,那么 Buffer.BlockCopy 是完全线程安全的。
  1. byte[] source1 = { 1, 2, 3 };
  2. byte[] destination1 = new byte[3];
  3. byte[] source2 = { 4, 5, 6 };
  4. byte[] destination2 = new byte[3];
  5. // 线程 1
  6. Task.Run(() => Buffer.BlockCopy(source1, 0, destination1, 0, 3));
  7. // 线程 2
  8. Task.Run(() => Buffer.BlockCopy(source2, 0, destination2, 0, 3));
复制代码
在这种环境下,两个线程互不干扰,Buffer.BlockCopy 可以安全地运行。
 
场景 2: 多个线程操作同一个数组
如果多个线程操作同一个数组,则必要特别警惕,确保不会发生数据竞争。
  1. byte[] sharedArray = new byte[10];
  2. // 线程 1
  3. Task.Run(() => Buffer.BlockCopy(new byte[] { 1, 2, 3 }, 0, sharedArray, 0, 3));
  4. // 线程 2
  5. Task.Run(() => Buffer.BlockCopy(new byte[] { 4, 5, 6 }, 0, sharedArray, 3, 3));
复制代码
在这个例子中,两个线程分别对 sharedArray 的不同部分进行操作,因此不会发生冲突。
但是,如果两个线程尝试同时写入 sharedArray 的同一部分,就会出现题目。
  1. // 线程 1
  2. Task.Run(() => Buffer.BlockCopy(new byte[] { 1, 2, 3 }, 0, sharedArray, 0, 3));
  3. // 线程 2
  4. Task.Run(() => Buffer.BlockCopy(new byte[] { 4, 5, 6 }, 0, sharedArray, 0, 3));
复制代码
这时,两个线程都试图将数据写入 sharedArray 的前 3 个字节,最终结果大概是不确定的。
 
场景 3: 使用锁掩护共享数组
如果必须对共享数组进行并发操作,可以通过加锁来确保线程安全:
  1. byte[] sharedArray = new byte[10];
  2. object lockObject = new object();
  3. // 线程 1
  4. Task.Run(() =>
  5. {
  6.     lock (lockObject)
  7.     {
  8.         Buffer.BlockCopy(new byte[] { 1, 2, 3 }, 0, sharedArray, 0, 3);
  9.     }
  10. });
  11. // 线程 2
  12. Task.Run(() =>
  13. {
  14.     lock (lockObject)
  15.     {
  16.         Buffer.BlockCopy(new byte[] { 4, 5, 6 }, 0, sharedArray, 3, 3);
  17.     }
  18. });
复制代码
通过加锁,可以确保每次只有一个线程能够操作共享数组,从而制止数据竞争。
 
总结


 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 qidao123.com技术社区-IT企服评测·应用市场 (https://dis.qidao123.com/) Powered by Discuz! X3.4