2010-06-22 161 views
1
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading; 

namespace ThreadDemo 
{ 
    class Program 
    { 
     static public List<int> temp = new List<int >(); 
     static public List<Thread> worker = new List<Thread>(); 
     static public List<List<int>> Temporary = new List<List<int>>(); 
     static void Main(string[] args) 
     { 
      temp.add(20); 
      temp.add(10); 
      temp.add(5); 
      foreach (int k in temp) 
      { 
       int z = 0; 
       worker[z] = new Thread(() => { sample(k); }); 
       worker[z].Name = "Worker" + z.ToString(); 
       worker[z].Start(); 
       z++; 
      } 
     } 
     public static void sample(int n) 
     { 
      List<int> local = new List<int>(); 
      for (int i = 0; i < n; i++) 
      { 
       local.Add(i); 
      } 
      Temporary.Add(local); 
     } 
    } 
} 
在這個程序時,啓動主程序foreach循環我有螺紋的問題

創建三級螺紋,也將啓動thread.In是第一個線程操作比其他不再那麼這將需要一些時間但其他線程在第一個 之前完成,因爲這個命令在臨時發生了變化。我需要臨時列表順序和臨時列表順序一樣。使用線程可以實現這個功能。線程同步

+1

只是關於語法的一些提示:在C#中,方法名通常以大寫字母開頭,變量/字段名以小寫字母開頭。 – Kiril 2010-06-22 05:45:31

+0

我知道lirik我只是輸入這個程序,例如無論如何謝謝你的評論 – ratty 2010-06-22 05:46:54

+0

沒問題...不要忘記,你可以編輯你的問題後,你已經提交它。如果你想修復語法,你可以編輯你的文章並修復它。 – Kiril 2010-06-22 05:48:55

回答

2

這裏是你的代碼快速刺:

class Program 
{ 
    static public List<int> temp = new List<int >(); 
    static public List<Thread> worker = new List<Thread>(); 
    static public List<List<int>> temporary = new List<List<int>>(); 
    static public object sync = new object(); 

    static void Main(string[] args) 
    { 
     temp.add(20); 
     temp.add(10); 
     temp.add(5); 

     // Add a corresponding number of lists 
     for(int i = 0; i < temp.Count; ++i) 
     { 
      temporary.Add(new List<int>); 
     } 

     // As Jon Skeet mentioned, z must be declared outside the for loop 
     int z = 0; 
     foreach (int k in temp) 
     { 
      // As Jon Skeet mentioned, you need to capture the value of k 
      int copy = k; 

      Thread t = new Thread(() => { Sample(copy, z); }); 
      t.Name = "Worker" + z.ToString(); 

      // set the thread to background, so your thread is 
      // properly closed when your application closes. 
      t.IsBackground = true; 
      t.Start(); 

      // Calling worker[z] will always going to be out of bounds 
      // because you didn't add anything to to the worker list, 
      // therefore you just need to add the thread to the worker 
      // list. Note that you're not doing anything with the worker 
      // list, so you might as well not have it at all. 
      worker.Add(t); 
      z++; 
     } 
    } 

    // Supply the order of your array 
    public static void Sample(int n, int order) 
    { 
     for (int i = 0; i < n; i++) 
     { 
      // Technically in this particular case you don't need to 
      // synchronize, but it doesn't hurt to know how to do it. 
      lock(sync) 
      { 
       temporary[order].Add(i); 
      } 
     } 
} 

現在的臨時列表應包含在正確的順序其他列表(與您的TMP順序)。您的標題確實提到了時間安排,但我不確定您爲什麼需要在此安排時間,或者您想了解有關安排時間的信息。

+0

謝謝你Y我們的答案我認爲這將幫助我 – ratty 2010-06-22 06:09:24

+0

@ratty,讓我知道如果你不理解它的一部分。 – Kiril 2010-06-22 06:22:25

1

首先,你的所有線程都是臨時收集,並且因爲List不是線程安全的,所以你應該同步你的線程以正確工作,第二,你沒有保證第一個線程會先完成,如果第一個線程先開始完成,找出核心如何安排線程。 要達到你想要的效果,你可以使用線程synchronization mechanisms

8

有三個問題。首先,變量捕獲:

foreach (int k in temp) 
{ 
    int z = 0; 
    worker[z] = new Thread(() => { sample(k); }); 
    ... 
} 

這是捕獲變量k在lambda表達式,而不是價值k。解決辦法是拍攝一份副本:

foreach (int k in temp) 
{ 
    int z = 0; 
    int copy = k; 
    worker[z] = new Thread(() => { sample(copy); }); 
    ... 
} 

有關更多信息,請參閱Eric Lippert's blog post

其次,你總是填充worker[0]因爲z將始終爲0如果你想填充其他元素,你需要外部聲明z。或者,您可以添加到列表中。

第三,存在不知道結果排序的問題。解決這個問題的最簡單方法實際上是將Temporary變成一個數組。再次捕獲變量的副本以保持正確的位置。正如ArsenMkrt所說,你還需要更新一個列表,這將涉及鎖定。

您是否正在使用.NET 4.0(或可以)?並行擴展使得所有這些,很多更簡單。

+0

啊,可變的捕獲...在我之前咬了我幾次。 +1只是爲了指出這一點! – Pwninstein 2010-06-22 05:31:52

+0

Skeet感謝您的回覆,我想知道您的解決方案清楚 – ratty 2010-06-22 05:37:19

+0

@ratty:哪種解決方案 - 修改您的或使用並行擴展?後者會更加簡單。 – 2010-06-22 06:04:04

0

如果您需要按順序排列線程結果,您應該或者以某種方式將它們傳遞給z,或者讓它們返回結果並按主線程中的順序連接每個線程。

除此之外,你可能會有點擰。無論你需要做什麼,線程本質上都傾向於在錯誤的時間運行。當你滿意時,你不能依靠他們來開始或停止;如果可以的話,整個類的併發問題就會消失。

我建議你少用一些線程。在單核,單CPU機器上,你的線程示例運行速度要比沒有線程的體面編碼解決方案慢,因爲在啓動線程時需要額外的開銷。我見過的唯一一次線程真的很有用,有時候你實際上需要出現一次做兩件事情。就像在等待輸入或在後臺執行一些任意大的工作時讓UI保持工作一樣。有線程爲了有他們將最終導致你瘋了。