【问题标题】:When is the work of a C# Parallel.ForEach done?C# Parallel.ForEach 的工作何时完成?
【发布时间】:2013-02-07 13:10:18
【问题描述】:

我正在用 C# 开发一个 MVC4 网站。以下代码应在将所有内容传递给视图之前使用项目填充 ConcurrentBag (DisplayModels)。

    Parallel.ForEach(model.Products, p =>
    {
        model.DisplayModels.Add(new DisplayBoardModel()
        {
            Market = model.Market,
            Product = p
        });
    });

    return View(model);

我发现在任何给定的执行中,DisplayModel 似乎都填充到了不同的点。好像 ForEach 在每个后台任务返回之前就完成了。

我对@9​​87654323@ 的理解是它并行处理每个项目,但仍然阻塞调用线程,直到它的所有工作完成。这不正确吗?

在模型准备好之前,我还应该做些什么来阻止动作返回?使用普通的foreach 效果很好

【问题讨论】:

    标签: c# multithreading concurrency asp.net-mvc-4 parallel-processing


    【解决方案1】:

    Parallel.ForEach() 工作正常,并按预期一次性完成。

    但是您的model.DisplayModels.Add() 可能不是线程安全的。你用的是什么系列?

    您可以通过以下方式解决此问题:a) 为 DisplayModels 使用 Concurrent 集合或 b) 将 ForEach 转换为 PLINQ 查询。但除非DisplayBoardModel() 做了一些繁重的 CPU 工作(而 ctor 通常不会),否则进行并行处理毫无意义。

    所以,只需使用简单的foreach()


    编辑,新信息

    每个 DisplayBoardModel 发出一个数据库请求

    所以这是一个潜在的原因。每个 Db 操作是否都创建自己的连接(上下文)?有没有机会默默地忽略异常?

    【讨论】:

    • OP 说它是ConcurrentBag
    • 谢谢@Henk。该集合是ConcurrentBag,因此.Add() 方法应该是安全的。并行的原因是每个DisplayBoardModel 都会发出一个数据库请求,这可能会有点慢
    • 好的,ConcurrentBag 在第一个帖子中吗?我错过了。 (编辑)。
    • 有人提到但我错过了数据库的东西,对不起。每个模型都有自己的 EF 上下文,用于数据库连接。我看不到任何可以静默丢弃异常的明显地方,我会进一步调查......
    • 也就是说,如果我使用普通的foreach,它每次都能完美运行,所以肯定唯一的异常可能是OutOfMemory,太多的数据库连接或与线程有关的东西游泳池?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-01
    • 1970-01-01
    • 2010-10-11
    • 1970-01-01
    相关资源
    最近更新 更多