并行功能,在C#中返回不同的结果

问题描述:

我在我的Windows窗体C#应用这些代码:并行功能,在C#中返回不同的结果

private void button7_Click(object sender, EventArgs e) 
{ 
    ThreadStart starter = delegate { thread_func(2, 1000000); }; 
    thread1_thread = new Thread(starter); 
    starter = delegate { thread_func(1000000, 2000000); }; 
    thread2_thread = new Thread(starter); 
    starter = delegate { thread_func(2000000, 3000000); }; 
    thread3_thread = new Thread(starter); 
    starter = delegate { thread_func(3000000, 4000000); }; 
    thread4_thread = new Thread(starter); 

    thread1_thread.Start(); 
    thread2_thread.Start(); 
    thread3_thread.Start(); 
    thread4_thread.Start(); 

} 

void thread_func(decimal input1,decimal input2) 
{ 
    for (; input1 < input2; input1++) 
    { 
     threadNumbers_list.Add(input1); 
     if (input1 % 2 != 0) 
     { 
      if (isPrime_func(input1)) 
      { 
       PrimeNumbers_decimal_list.Add(input1); 
      } 
     } 
    } 
} 
public static Boolean isPrime_func(decimal number) 
    { 
     decimal boundary = (decimal)Math.Floor(Math.Sqrt((double)number)); 

     if (number == 1) return false; 
     if (number == 2) return true; 

     for (decimal i = 2; i <= boundary; ++i) 
     { 
      if (number % i == 0) return false; 
     } 

     return true; 
    } 

我每次运行单击该按钮,我得到不同的结果。我尝试了很多东西,但无法弄清楚为什么会发生这种情况。即使是在较低的范围内发生。例如,在100个数字的范围内,它总是给出相同的结果。 有些时候,我的清单计数达到283138,有时候是283131和其他接近的数字。

另一个奇怪的是,当我评论检查偶数时,操作比此模式花费的时间更短。怎么了?

+5

'threadNumbers_list'和'PrimeNumbers_decimal_list'可能不是线程安全的。 –

+0

我创建该列表只是为了检查是否所有迭代都发生! – ACE

+1

'PrimeNumbers_decimal_list'呢?另外,你如何等待线程完成?你使用'Thread.Join'吗? –

当多个线程访问列表时,该列表必须是线程安全的,否则您将遇到很多问题。

.NET提供了一些类似ConcurrentQueue<T>类的thread-safe collections

附注:请考虑使用Tasks而不是线程。此外,.NET框架supports data parallelism via the Parallel class。考虑使用这样的类代替。

关于性能,当你不检查,如果数为偶数,我本地测试这一点,我得到了以下数字:

  • 它需要〜76秒当我不,如果数量检查甚至。
  • 当我检查数字是否均匀时,需要约66秒。

所以这与您的测量不符。这可能是由您测量的方式引起的。我有一个Stopwatch这样测量:

//... 

Stopwatch sw = Stopwatch.StartNew(); 

thread1_thread.Start(); 
thread2_thread.Start(); 
thread3_thread.Start(); 
thread4_thread.Start(); 

thread1_thread.Join(); 
thread2_thread.Join(); 
thread3_thread.Join(); 
thread4_thread.Join(); 

long result = sw.ElapsedMilliseconds; 

//... 

顺便说一句,这里的东西,你能做到这一点可能会节省一些执行时间为您提供:

创建为thread_func内的每个线程正常List<T>实例方法,以便您不会遇到多线程问题。然后在循环结束后,您可以从本地列表更新主列表。只更新主列表必须是线程安全的。在这种情况下,我宁愿主列表是正常的List<T>,并且您使用lock关键字来同步对它的访问,因为您只需要更新它4次(线程数)。

+0

你能帮助我,请让它线程安全!? – ACE

+0

'PrimeNumbers_decimal_list'的定义是什么?它是一个列表'?您可以将其更改为'ConcurrentQueue '并使用['Enqueue'](https://msdn.microsoft.com/en-us/library/dd287262(v = vs.110).aspx)方法而不是'添加'方法。 –

+0

好的谢谢,我要检查它。 列表 PrimeNumbers_decimal_list =新列表(); – ACE