为什么我的线程池的线程不能同时完成

时间:2017-05-25 06:13:29

标签: c# multithreading threadpool thread-sleep queueuserworkitem

在main函数中,我编写了这段代码:

            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秒,从我的理解,这100个线程或许不能同时完成,但也不能有这么多时间不同。

我也设置了

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;
            }

        }
    }

2 个答案:

答案 0 :(得分:1)

在您的示例中,线程未同时启动。在 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);
    }

答案 1 :(得分:0)

好问题。

线程拉取中线程的执行取决于很多因素,其中一个因素是cpu核心。它将线程放在每个核心中运行,一旦完成它就会放入另一个核心。

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

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