【问题标题】:C#: Parallel foreach calling a function inside the loop [closed]C#:并行foreach调用循环内的函数[关闭]
【发布时间】:2023-03-24 20:27:01
【问题描述】:

我有一个函数,我试图在 Parallel foreach 中调用它。由于变量是线程不安全的,我得到了意想不到的结果。

但根据官方网站“Parallel 的所有公共和受保护成员都是线程安全的,并且可以从多个线程同时使用。”所以我不明白为什么它是线程不安全的

我第一次使用 Parallel.ForEach

            Parallel.ForEach(distinctUrls, new ParallelOptions {MaxDegreeOfParallelism = executionContext.MaxDegreeOfParallelism.Value}, siteUrl =>
            {
                WriteSiteCollection (Ds, executionContext, siteUrl, stopwatch, runtime);
            });

然后我切换到 Parallel.For 但我得到了相同的结果

            Parallel.For(0, distinctUrls.Count, new ParallelOptions { MaxDegreeOfParallelism = executionContext.MaxDegreeOfParallelism.Value }, i =>
            {
                WriteSiteCollection(Ds, executionContext, distinctUrls[i], stopwatch, runtime);
            });

任何提示或想法我该如何解决这个问题。或者如何使用线程安全变量调用 Parallel.ForEach 中的函数。

【问题讨论】:

  • 我们不知道该 write 方法中的内容,但 Parallel.For 是线程安全的并不意味着您调用的方法是。
  • 因为我在 distinctUrls[i] 中得到 2 个值。但它只写了一个。没有并行执行的相同方法工作正常
  • i = Interlocked.Increment(ref i); 为什么将其分配给i(本身)?你不应该那样做。相反,使用stackoverflow.com/a/39714239/34092Parallel 为您处理索引生成。
  • 另外,您还没有提供minimal reproducible example,因为WriteListItems 可能有类似的错误。这样想minimal reproducible example - 我可以将它复制并粘贴到控制台应用程序中并运行它吗?如果我不能 - 它可能还不是minimal reproducible example

标签: c# multithreading c#-4.0 parallel-processing thread-safety


【解决方案1】:

一个常见的错误是,虽然对象是线程安全的,但集合不是。

因此,在枚举您的集合时,可能有人更改了集合(通过添加 [或更糟:删除] 项目)。

这会产生不必要的副作用并使其线程不安全。


根据您的情况,您可以通过确保在处理过程中不能更改集合或创建它的本地副本来克服这个问题。

此外:

没有足够的信息来回答您的问题。那些 "unexpected results" 是什么,也许WriteSiteCollection 根本不是线程安全的。所以也许你可以给我们看那段代码。

【讨论】:

  • 在最简单的情况下, distinctUrls 中只有 2 个值。在函数中,我没有更改集合。它仅用于指定在哪个 url 中写入。但在这两种情况下,程序都在写入同一个 Url
  • executionContext 这个变量很重要。所以在函数内部调用函数后我应该复制它?
  • @Student:没有足够的信息来回答你的问题。那些unexpected 是什么,也许WriteSiteCollection 不是线程安全的。所以也许你可以给我们看那段代码。
  • 以意想不到的方式; distinctUrls 中有两个 url。但结果只写在一个 url 中。另一个完全是空的。在 executionContext.Url 中有要写的 Url。有没有办法让它在整个循环执行中保持修复。它在代码中的任何地方都没有改变,但因为它是并行执行的,所以另一个循环导致值不同
猜你喜欢
  • 1970-01-01
  • 2016-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-15
相关资源
最近更新 更多