RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 821107
Accepted
Иван К
Иван К
Asked:2020-04-29 22:11:23 +0000 UTC2020-04-29 22:11:23 +0000 UTC 2020-04-29 22:11:23 +0000 UTC

这段代码需要锁吗?

  • 772

如果我要在 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 =>
{
    //тут ещё какие то действия
});
c#
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. andreycha
    2020-04-30T20:31:35Z2020-04-30T20:31:35Z

    关于SynchronizationLockException. 您的方法返回IEnumerable. 当您将此方法指定为 的数据源时Parallel.ForEach(),这意味着序列的不同元素可以由不同的线程请求和处理。

    但这就是它发挥作用的地方yield return。使用这种结构,迭代器的工作方式略有不同:

    1. 该方法开始执行,循环的第一次迭代发生。
    2. 该方法返回序列的第一个元素,而循环的第一次迭代还没有结束。
    3. 当请求下一个元素时,第一次迭代结束,第二次开始,并返回第二个元素。第二次迭代也没有完成。
    4. 就这样围成一圈。

    现在如果我们结合Parallel.ForEach(),yield return和lock,我们会得到以下场景:

    1. 第一个线程请求第一个元素:执行循环的第一次迭代,获取锁,返回第一个元素。锁没有被释放。
    2. 第二个线程请求下一个元素:第一次迭代完成,代码尝试释放锁,我们得到一个异常SynchronizationLockException,表明线程试图调用它不拥有的监视器方法。因为第一个线程进入了监视器,而第二个线程试图退出它。
    • 4
  2. Best Answer
    Alexander Petrov
    2020-04-30T17:37:43Z2020-04-30T17:37:43Z

    该方法不需要此代码中的Parallel.ForEach运算符。lock

    参数source- 源 - 在一个线程中执行。但是body- 主体 - 可以在多个线程中执行(或者可能在一个线程中)。


    我注意到阻塞this是危险的。如果其他人锁定了这个类的同一个对象,那么这可能会导致死锁。

    • 3

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    是否可以在 C++ 中继承类 <---> 结构?

    • 2 个回答
  • Marko Smith

    这种神经网络架构适合文本分类吗?

    • 1 个回答
  • Marko Smith

    为什么分配的工作方式不同?

    • 3 个回答
  • Marko Smith

    控制台中的光标坐标

    • 1 个回答
  • Marko Smith

    如何在 C++ 中删除类的实例?

    • 4 个回答
  • Marko Smith

    点是否属于线段的问题

    • 2 个回答
  • Marko Smith

    json结构错误

    • 1 个回答
  • Marko Smith

    ServiceWorker 中的“获取”事件

    • 1 个回答
  • Marko Smith

    c ++控制台应用程序exe文件[重复]

    • 1 个回答
  • Marko Smith

    按多列从sql表中选择

    • 1 个回答
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Suvitruf - Andrei Apanasik 什么是空? 2020-08-21 01:48:09 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5