如果我要在 Parallel.ForEach 中使用它,你能告诉我这个代码是否需要锁吗?带锁的代码示例:
private IEnumerable<(Byte[] part_bytes, Int32 part_number)> GetPartsFile(FileStream file_stream)
{
file_stream.Seek(offset: 0, origin: SeekOrigin.Begin);
for (Int32 index = 0, part_number = 0; index < file_stream.Length; index += DefaultCopyBufferSize, part_number++)
{
lock (this)
{
Byte[] bytes = new Byte[DefaultCopyBufferSize];
Int32 readed_bytes = file_stream.Read(array: bytes, offset: index, count: DefaultCopyBufferSize);
if (readed_bytes < DefaultCopyBufferSize)
{
Byte[] end_bytes = new Byte[readed_bytes];
Buffer.BlockCopy(src: bytes, srcOffset: 0, dst: end_bytes, dstOffset: 0, count: readed_bytes);
yield return (end_bytes, part_number);
}
else
{
yield return (bytes, part_number);
}
}
}
}
使用 Parallel.ForEach 的示例:
Parallel.ForEach(
source: GetPartsFile(file_stream: zip_file),
body: tuple =>
{
//тут ещё какие то действия
});
关于
SynchronizationLockException
. 您的方法返回IEnumerable
. 当您将此方法指定为 的数据源时Parallel.ForEach()
,这意味着序列的不同元素可以由不同的线程请求和处理。但这就是它发挥作用的地方
yield return
。使用这种结构,迭代器的工作方式略有不同:现在如果我们结合
Parallel.ForEach()
,yield return
和lock
,我们会得到以下场景:SynchronizationLockException
,表明线程试图调用它不拥有的监视器方法。因为第一个线程进入了监视器,而第二个线程试图退出它。该方法不需要此代码中的
Parallel.ForEach
运算符。lock
参数
source
- 源 - 在一个线程中执行。但是body
- 主体 - 可以在多个线程中执行(或者可能在一个线程中)。我注意到阻塞
this
是危险的。如果其他人锁定了这个类的同一个对象,那么这可能会导致死锁。