【问题标题】:Correct use of Parallel for loop in C#?在 C# 中正确使用并行 for 循环?
【发布时间】:2013-01-08 18:53:35
【问题描述】:

在这个例子中,如果我想一次将可以执行函数DoWork 的线程数限制为十个,那么这是正确使用Parallel.For 循环吗?是否会阻塞其他线程,直到十个线程之一可用?如果不是,有什么更好的多线程解决方案仍然可以让我执行该功能 6000 多次?

class Program
{
    static void Main(string[] args)
    {
        ThreadExample ex = new ThreadExample(); 
    }
}

public class ThreadExample
{
    int limit = 6411; 

    public ThreadExample()
    {
        Console.WriteLine("Starting threads...");
        int temp = 0; 
        Parallel.For(temp, limit, new ParallelOptions { MaxDegreeOfParallelism = 10 }, i =>
        {
            DoWork(temp);
            temp++; 
        }); 
    }

    public void DoWork(int info)
    {
        //Thread.Sleep(50); //doing some work here. 

        int num = info * 5; 

        Console.WriteLine("Thread: {0}      Result: {1}", info.ToString(), num.ToString());
    }
}

【问题讨论】:

  • temp++ 不是线程安全的。
  • @SLaks 是的,它不是线程安全的,但它在这场比赛中有意义吗? Parallel.For 是如何工作的?
  • @HamletHakobyan 你是什么意思?程序员的意图很明确;他想计算已完成任务的数量。实际发生的情况并不相同,因为竞争条件可能会导致计数器未正确递增。使用interlocked.Exchange 可以解决这个问题。至于Paralle.For,它是一个for 循环,其迭代由多个线程(在一定程度上)并行执行。
  • @Servy 你有错字Interlocked.Increment 必须是。但也不是必需的,如Mattias Buelens 中所述,答案循环计数器是内部组织的,temp 在这种情况下并不实际。

标签: c# multithreading


【解决方案1】:

您需要使用传递给 lambda 函数的 i 作为索引。 Parallel.For 让您从使用循环计数器的麻烦中解脱出来,但您需要使用它!

    Parallel.For(0, limit, new ParallelOptions { MaxDegreeOfParallelism = 10 }, i =>
    {
        DoWork(i);
    });

至于你的其他问题:

  • 是的,这将正确限制同时工作的线程数量。
  • 没有线程被阻塞。迭代被排队,一旦线程可用,它就会从队列中获取下一次迭代(以同步方式)进行处理。

【讨论】:

  • MaxDegreeOfParallelism 正是您所寻找的
  • @MicahArmantrout 他已经在 OP 中使用它;这不是给他带来麻烦的原因。此答案正确识别了 OP 代码的问题。
  • 这是 OPs 解决方案的一个问题,但它不能回答所提出的任何特定问题(“这样可以吗?”除外)。
  • @Servy 我想念理解...这仍然是正确答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-16
  • 2013-02-16
  • 2015-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多