2016-02-17 33 views
1

我在我的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'嗎? –

回答

2

當多個線程訪問列表時,該列表必須是線程安全的,否則您將遇到很多問題。

.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