1:网摘一段话:不同的托管环境会设置不同的上限。如在.NET 2.0 SP1之后,普通的Windows应用程序(如控制台或WinForm/WPF),会将其设置为“处理器数 * 250”。也就是说,如果您的机器为2个2核CPU,那么CLR线程池的容量默认上限便是1000,也就是说,它最多可以管理1000个线程同时运行——很多情况下这已经是一个很可怕的数字了,如果您觉得这还不够,那么就应该考虑一下您的实现方式是否可以改进了。2:看我的一段代码:
class Program
    {
      static void Main(string[] args)
        {
            WaitCallback callBack = new WaitCallback(PooledFunc);
            ThreadPool.QueueUserWorkItem(PooledFunc, "张三");
            ThreadPool.QueueUserWorkItem(callBack,"李四");
            ThreadPool.QueueUserWorkItem(callBack,"王二");          
            Console.ReadLine();
        }
      static void PooledFunc(object state)
        {
            Console.WriteLine("当前线程的标识符是: {0}", Thread.CurrentThread.ManagedThreadId);
            Console.WriteLine("{0}开始从服务器下载文件", (string)state);
            int ticks = Environment.TickCount;
            while (Environment.TickCount - ticks < 2000) ;  //CPU一直处于忙碌
            Console.WriteLine("{0}下载完了....", (string)state);
        }
}上面的代码,线程池中,并没有三条线程同时执行,王二那条线程是在张三线程执行完之后才执行的,并且从ManagedThreadId值可以看出,王二和张三使用的是同一条线程。而上面那段话,不是说的可以有1000条线程同时执行的吗?我的电脑的CPU是2核的怎么才2条线程同时执行呢?

解决方案 »

  1.   

    你让李四和王二拖慢一点啊!如果它们一瞬间就完成了,电脑再去选择两个不同的线程那么就太低估系统线程池的智慧(复用性)了。
    如果你的程序是故意想“烧热CPU来取暖”,那么可以这样写。否则,一个异步的编程不是这样写的。它可能是类似于:var gate1 = new ManualResetEvent(false);
    //注册第一个线程,并且将gate1作为参数,线程执行完之前执行gate1的Set方法。
    var gate2 = new ManualResetEvent(false);
    //注册第一个线程,并且将gate2作为参数,线程执行完之前执行gate2的Set方法。
    var gate3 = new ManualResetEvent(false);
    //注册第一个线程,并且将gate3作为参数,线程执行完之前执行gate3的Set方法。
    WaitHandle.WaitAll(new WaitHandle[] { gate1, gate2, gate3 });
    这就会阻塞直到三个线程都执行完才继续。此时不必写一个循环语句去烧CPU。
      

  2.   

    注册第一个线程  -->  注册一个线程这个注册就是指你的QueueUserWorkItem,或者是new一个thread对象等,任何一种使用线程的方式都可以。
      

  3.   

    其实任何“阻塞方式”的线程程序都可能不是合适的异步程序。很多时候,既然你要阻塞,那么可能就是用多线程的语法来写同步程序,这反而不如直接写同步顺序执行的程序。
    异步程序的基本思维就是回调式的。例如PooledFunc("张三", myCallBack);这个语句发出,那么一瞬间这个语句就执行完了。因为它只是注册线程而已。使用异步编程,其实应该改变我们的思维习惯。你首先要把你的程序系统按照异步回调的思维方式重新表达,甚至重新研究业务逻辑,才能写好异步程序。主要就是要突出这个“回调处理”的作用,好的异步程序几乎不用同步阻塞。否则,如果你的思维总是函数式思维,你的思维上就是“调用-返回值,然后再调用-返回值”这种同步顺序思维模式,那么很多人会滥用阻塞方法,用线程/异步的语法去模拟同步程序的处理流程,其实写不好异步程序。
      

  4.   

    ThreadPool的作用在于更有效的利用线程。尽量少的去开新线程,而使用人家已经用完的线程。
    线程池分配线程的流程是这样的
    1.请求线程池分配线程
    2.线程池查询可用线程池队列中的线程。
    2.1.如果有可用线程,则使用可用线程,将可用线程从可用线程队列。
    2.2.1.如果没有可用线程,并且线程池未达到上限,则新创建1个工作线程,并加入到线程池中。
    2.2.2.如果没有可用线程,并且线程池已经达到上限,则等待任意一条线程池中的线程工作完毕,再回到第二步。
    3.线程工作完毕后,通知线程池线程工作完毕。线程池将此线程放入到可用线程池。ThreadPool简单理解,就是用 Monitor 和 Thread 2个类的进一步封装。线程池中包含2种不同类型的线程,1种是工作线程,1种是IO线程。他们的工作内容不同,但都占用一个线程。如果你真想开N条线程的话,建议直接使用Thread去创建。
      

  5.   

    http://blog.csdn.net/manbufenglin/article/details/6655716
      

  6.   


    是由两个因素决定的,一是MinThreads,你的是双核 那么默认的MinThreads的个数就是2你可以用ThreadPool.SetMinThreads 来设置MinThreads的个数第二个因素是  while (Environment.TickCount - ticks < 2000) ;因为CPU一直在工作,没办法让最小线程数之外的线程来处理只能等待CPU的某个核心处理完,才会让其他线程来工作,所以只有两条线程运行关于线程ID 是两个,如果你设置成 while (Environment.TickCount - ticks < 5000) ;你会看到线程ID会不一致,但依然只会有两个线程在同时工作因为你的CPU是双核,任意一个线程的工作都是一直让CPU满负载  那么只会有两个线程同时在工作简单的改法就是 while (Environment.TickCount - ticks < 2000) ;
    =>
    Thread.Sleep(2000);