2010-06-22 121 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保持工作一样。有线程为了有他们将最终导致你疯了。