为什么我的线程池的线程不会在同一时间完成

问题描述:

在主函数中,我写这篇文章的代码:为什么我的线程池的线程不会在同一时间完成

  ThreadPool.SetMaxThreads(200, 200); 

     for (int i = 0; i < 100; i++) 
     { 
      ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadWhichWillCallSQL_test), i); 
      Thread.Sleep(1); 
     } 

和线程功能是象下面这样:

 static public void ThreadWhichWillCallSQL_test(Object o1) 
    { 
     Thread.Sleep(5000); 
     Console.WriteLine(DateTime.Now.ToString()); 
     return; 
    } 

输出为:

5/25/2017 2:00:01 PM 
5/25/2017 2:00:01 PM 
5/25/2017 2:00:01 PM 
5/25/2017 2:00:01 PM 
5/25/2017 2:00:02 PM 
5/25/2017 2:00:03 PM 
5/25/2017 2:00:04 PM 
5/25/2017 2:00:05 PM 
5/25/2017 2:00:05 PM 
5/25/2017 2:00:06 PM 
5/25/2017 2:00:06 PM 
5/25/2017 2:00:06 PM 
5/25/2017 2:00:06 PM 
5/25/2017 2:00:07 PM 
5/25/2017 2:00:07 PM 
5/25/2017 2:00:08 PM 
5/25/2017 2:00:08 PM 
5/25/2017 2:00:09 PM 
5/25/2017 2:00:09 PM 
5/25/2017 2:00:10 PM 
5/25/2017 2:00:10 PM 
5/25/2017 2:00:10 PM 
5/25/2017 2:00:11 PM 
5/25/2017 2:00:11 PM 
5/25/2017 2:00:11 PM 
5/25/2017 2:00:11 PM 
5/25/2017 2:00:12 PM 
5/25/2017 2:00:12 PM 
5/25/2017 2:00:12 PM 
5/25/2017 2:00:13 PM 
5/25/2017 2:00:13 PM 
5/25/2017 2:00:13 PM 
5/25/2017 2:00:14 PM 
5/25/2017 2:00:14 PM 
5/25/2017 2:00:14 PM 
5/25/2017 2:00:15 PM 
5/25/2017 2:00:15 PM 
5/25/2017 2:00:15 PM 
5/25/2017 2:00:15 PM 
5/25/2017 2:00:16 PM 
5/25/2017 2:00:16 PM 
5/25/2017 2:00:16 PM 
5/25/2017 2:00:16 PM 
5/25/2017 2:00:17 PM 
5/25/2017 2:00:17 PM 
5/25/2017 2:00:17 PM 
5/25/2017 2:00:17 PM 
5/25/2017 2:00:18 PM 
5/25/2017 2:00:18 PM 
5/25/2017 2:00:18 PM 
5/25/2017 2:00:18 PM 
5/25/2017 2:00:19 PM 
5/25/2017 2:00:19 PM 
5/25/2017 2:00:19 PM 
5/25/2017 2:00:19 PM 
5/25/2017 2:00:20 PM 
5/25/2017 2:00:20 PM 
5/25/2017 2:00:20 PM 
5/25/2017 2:00:20 PM 
5/25/2017 2:00:20 PM 
5/25/2017 2:00:21 PM 
5/25/2017 2:00:21 PM 
5/25/2017 2:00:21 PM 
5/25/2017 2:00:21 PM 
5/25/2017 2:00:22 PM 
5/25/2017 2:00:22 PM 
5/25/2017 2:00:22 PM 
5/25/2017 2:00:22 PM 
5/25/2017 2:00:22 PM 
5/25/2017 2:00:23 PM 
5/25/2017 2:00:23 PM 
5/25/2017 2:00:23 PM 
5/25/2017 2:00:23 PM 
5/25/2017 2:00:23 PM 
5/25/2017 2:00:24 PM 
5/25/2017 2:00:24 PM 
5/25/2017 2:00:24 PM 
5/25/2017 2:00:24 PM 
5/25/2017 2:00:24 PM 
5/25/2017 2:00:25 PM 
5/25/2017 2:00:25 PM 
5/25/2017 2:00:25 PM 
5/25/2017 2:00:25 PM 
5/25/2017 2:00:25 PM 
5/25/2017 2:00:25 PM 
5/25/2017 2:00:26 PM 
5/25/2017 2:00:26 PM 
5/25/2017 2:00:26 PM 
5/25/2017 2:00:26 PM 
5/25/2017 2:00:27 PM 
5/25/2017 2:00:27 PM 
5/25/2017 2:00:27 PM 
5/25/2017 2:00:27 PM 
5/25/2017 2:00:27 PM 
5/25/2017 2:00:27 PM 
5/25/2017 2:00:28 PM 
5/25/2017 2:00:28 PM 
5/25/2017 2:00:28 PM 
5/25/2017 2:00:28 PM 
5/25/2017 2:00:28 PM 

你可以注意到,所有线程完成的整个过程持续了将近28秒,从我的理解,这10个0线程也许不能同时完成,但也不能有那么多时间不同。

还我已成立

ThreadPool.SetMaxThreads(200, 200); 

,并只分配100个线程,所以不应该有任何线程等待别人停下来,对不对?

这里是完整的代码

 using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Text; 
    using System.Threading.Tasks; 
    using System.Threading; 

    namespace ThreadpoolDelay 
    { 
     class Program 
     { 
      static void Main(string[] args) 
      { 
       try 
       { 
        ThreadPool.SetMaxThreads(200, 200); 

        for (int i = 0; i < 30; i++) 
        { 
         ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadWhichWillCallSQL_test), i); 
        } 
       } 
       catch (Exception e) 
       { 
        Console.WriteLine(e.ToString()); 
       } 

       Console.WriteLine("\nPress ENTER to continue..."); 
       Console.Read(); 
      } 
      public static void ThreadWhichWillCallSQL_test(Object o1) 
      { 
       Thread.Sleep(5000); 
       Console.WriteLine(DateTime.Now.ToString()); 
       return; 
      } 

     } 
    } 
+0

我的环境是的Visual Studio 2012和.NET Framework 4.5 – yangl

+1

只能猜测,没有回答,没有好[mcve],可靠地再现问题。但是,'SetMaxThreads()'不会将新的活动线程添加到线程池中。它只是设置最大可能。因此,您仍然必须等待线程池被更多线程填充,因为您现有的工作项目需要很长时间。如果你运行两次测试会发生什么?它是否像你期待的那样第二次工作?为什么你甚至在乎?你真的有一个100核心机器? –

+0

嗨,我没有100核心机器,但我的机器可以运行30个线程我想,当我使用30个线程进行测试时,最早的和最新的线程完成时间仍然有11秒不同,我已将完整的代码添加到此post – yangl

线程不被在你的榜样,同时开始。添加以下调用后右SetMaxThreads

ThreadPool.SetMinThreads(200, 200); 

这将使线程同时启动。这是关于ThreadPool线程创建机制的东西。我建议阅读ThreadPool documentation了解详情。

更恰当地对其进行调试,更新ThreadWhichWillCallSQL_test方法来添加启动时间太长:

static void ThreadWhichWillCallSQL_test(object o1) 
    { 
     Console.WriteLine("start:" + DateTime.Now); 
     Thread.Sleep(5000); 
     Console.WriteLine("finish: " + DateTime.Now); 
    } 
+0

令人惊叹的是,它作品。是的,我没有仔细阅读文档,只是复制并合并其他人的代码。谢谢 。 – yangl

很好的问题。

执行线程中的线程取决于许多因素,其中一个因素是cpu核心。它把线程运行在每个核心上,一旦完成,就把另一个核心运行起来。

例如:如果有4个核心cpu。它同时并行放置4个线程,然后在线程完成任务时放入下一个线程。机制就像那些不完全一样。 你还有5秒延迟(线程睡眠),所以 计算就像是如果有4个核心:(30线程/ 4核心)* 5有些不像那些。

还可以看到有更多的信息:https://msdn.microsoft.com/en-us/library/3dasc8as(v=vs.80).aspx

+1

不是。池如何分配线程是一个实现细节,对于不同的版本它可能会有很大的不同。但合理的是,它不会为每个内核分配一个线程。 –

+0

同意adrino但分配multipal线程到核心和切换它们之间的上下文 –

+1

上下文切换?当然是。如果池为每个请求分配一个线程,那么总执行时间将约为5秒(忽略任何开销)。每个核心一个?它分配更多的线程,根据复杂的策略创建新的线程,直到最大OP集。短期生活操作的完美行为。当然,使用池分配30个长时间的延迟可以解决这个问题,但这只是人为的。 –