C# 为什么我的线程池';s线程不会同时完成

C# 为什么我的线程池';s线程不会同时完成,c#,multithreading,threadpool,thread-sleep,queueuserworkitem,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); }

在main函数中,我编写以下代码:

            ThreadPool.SetMaxThreads(200, 200);

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

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

        }
    }
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
使用系统线程;
命名空间线程池延迟
{
班级计划
{
静态void Main(字符串[]参数)
{
尝试
{
SetMaxThreads(200200);
对于(int i=0;i<30;i++)
{
QueueUserWorkItem(新的WaitCallback(ThreadWhichWillCallSQL_测试),i);
}
}
捕获(例外e)
{
Console.WriteLine(如ToString());
}
Console.WriteLine(“\n按ENTER继续…”);
Console.Read();
}
将调用SQL\U测试的公共静态无效线程(对象o1)
{
睡眠(5000);
Console.WriteLine(DateTime.Now.ToString());
返回;
}
}
}
问得好

线程拉取中线程的执行取决于许多因素,其中一个因素是cpu核心。它将线程放在每个内核中运行,完成后再放另一个

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


您还可以在此处查看更多信息:

在您的示例中,线程不是同时启动的。在SetMaxThreads之后添加以下调用

这将使线程同时启动。这是关于线程池线程创建机制的内容。我建议详细阅读

要更正确地调试,请更新线程,该线程将调用SQL\u测试方法以添加开始时间:

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

我的环境是Visual studio 2012和.net FrameWork 4.5,如果没有可靠地再现问题的良好工具,人们只能猜测,不能回答。但是,
SetMaxThreads()
不会向线程池添加新的活动线程。它只是设置了可能的最大值。因此,您仍然必须等待线程池中填充更多线程,因为现有工作项花费的时间太长。如果运行两次测试会发生什么?它是否像你第二次期望的那样工作?你为什么这么在乎?你真的有100核的机器吗?嗨,我没有100核的机器,但是我的机器可以运行30个线程,我想,当我使用30个线程进行测试时,最早和最晚的线程完成时间仍然有11秒的不同,我已经在这篇文章中添加了完整的代码作为问题/答案指出,你看错了方向。这并不是说他们没有在同一时间结束。这是因为线程池需要时间向池中添加更多线程。所以它们不是在同一时间开始的。不是真的。池如何分配线程是一个实现细节,对于不同的版本可能会有所不同。然而,它并没有为每个核心分配一个线程,而是为核心分配多线程,并在上下文切换之间切换上下文?当然可以。若池为每个请求分配一个线程,那个么总执行时间大约为5秒(忽略任何开销)。每个核心一个?它分配更多的线程,在需要时根据复杂的策略创建新线程,直到最大操作集。短命手术的完美行为。当然,使用池来分配30个长延迟会利用这个问题,但这只是人为的。当一个线程睡眠时,同一个内核会被许多其他线程使用(这是一个在亲和性、有利于缓存和保持所有内核忙碌、有利于并行性之间的折衷),感谢Adriano Repetti的精彩解释,它起作用了。是的,我没有认真阅读文档,只是复制并合并其他人的代码。非常感谢。
ThreadPool.SetMinThreads(200, 200);
    static void ThreadWhichWillCallSQL_test(object o1)
    {
        Console.WriteLine("start:"  + DateTime.Now);
        Thread.Sleep(5000);
        Console.WriteLine("finish: " + DateTime.Now);
    }