【问题标题】:Why Thread.Sleep affects creation of new Tasks?为什么 Thread.Sleep 会影响新任务的创建?
【发布时间】:2014-11-26 06:35:42
【问题描述】:
private static void Main(string[] args)
{
    for (int i = 0; i < 1000; i++)
    {
        Task.Factory.StartNew(() =>
        {
            Thread.Sleep(1000);
            Console.WriteLine("hej");
            Thread.Sleep(10000);
        });    
    }
    Console.ReadLine();
}

为什么这段代码不会在一秒钟后打印 1000 次“hej”?为什么 Thread.Sleep(10000) 对代码行为有影响?

【问题讨论】:

  • 你观察到什么行为?
  • 线程池管理器不会过多考虑您启动一千个线程的尝试。它让其中的一些线程松了,但是你的程序在所有这些线程上都陷入了困境,这些线程保持忙碌但根本没有做任何有用的事情。它偶尔会允许额外的线程开始运行。

标签: c# multithreading task threadpool


【解决方案1】:

Factory.StartNew 有效地将工作委托给ThreadPool

只要线程数小于或等于处理器数,线程池就会立即创建线程数来响应请求。一旦达到处理器计数,线程池将立即停止创建新线程。这是有道理的,因为创建的线程数量超过处理器数量会引入 线程调度 开销并且什么也不返回。

相反,它会限制线程的创建。它等待 500 毫秒以查看是否有任何工作仍在等待处理并且没有线程来处理请求。如果有待处理的作品,它将引入一个新线程(只有一个)。只要您有足够的工作要做,这个过程就会继续进行。

当工作队列的流量被清除时,线程池将销毁线程。上面提到的过程还在继续。

另外,有一个max limit 表示线程池可以同时运行的线程数。如果你点击它,线程池将停止创建更多线程并等待以前的工作项完成,以便它可以重用现有线程。

这不是故事的结局,而是令人费解的!这些是 ThreadPool 做出的几个决定。

我希望现在你会明白为什么你会看到你所看到的。

【讨论】:

    【解决方案2】:

    有许多因素会改变结果。

    一些存在(但不限于):

    • 循环迭代的固有时间
    • 线程池的大小
    • 线程管理开销

    【讨论】:

      【解决方案3】:

      您编码的行为方式是预期行为。您等待 1000 毫秒打印 hej 并在打印之后再执行 Thread.sleep 10000 毫秒。如果您想在一秒钟后打印 1000 次 hej,请删除 Thread.sleep(10000)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-07-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多