少有人走的路

勇哥的工业自动化技术网站

Task.Factory.StartNew为啥同一次添加10几个线程,超过8个后面添加的线程变开始变慢


勇哥描述一下:

如下面代码,当循环Task.Factory.StartNew到第9个的时候,会发现要隔约1秒才可以添加第9个,后面的第10,11,12,13,14 都要间格较长时间。

如果你把下面代码中的while死循环去掉,则15个线程瞬间添加完成。

这是什么原因呢?

 for (int i = 0; i < 15; i++)
            {
                var t1 = Task.Factory.StartNew(fun);
                taskList.Add(t1);
            }
            
 
        private void fun()
        {
            OutMsg($"id={Thread.CurrentThread.ManagedThreadId}, 启动时间:{DateTime.Now.ToString("hh:mm:ss:ms")}\n");
            Stopwatch sw1 = new Stopwatch();
            sw1.Start();
            while (true)
            {
               
                Thread.Sleep(5);
                if (sw1.ElapsedMilliseconds > 4000)
                {
                    sw1.Stop();
                    OutMsg($"id={Thread.CurrentThread.ManagedThreadId}, 退出时间:{DateTime.Now.ToString("hh:mm:ss:ms")}\n");
                    break;
                }
            }
        }


勇哥直接说答案:


用下面代码测试。

线程池最大允许线程数: 指的是你的cpu最大允许创建的线程总数,超过这个数再创建的就要排队了。

最小可用线程数: 就是你一次最多可以添加的线程数量,它的默认值就是你的cpu数量,如果图2所示。

                           本文的问题就是因为这个最小可用线程数太小,超过8个的线程添加就要排队,可以用ThreadPool.SetMinThreads() 来增加这个最小线程数

可用辅助线程的数目:  当你添加一个线程时,图1所示的“可用辅助线程的数目”就会减1


int data1, data2;
            ThreadPool.GetAvailableThreads(out data1, out data2);
            int data3, data4;
            ThreadPool.GetMinThreads(out data3, out data4);
            int d5, d6;
            ThreadPool.GetMaxThreads(out d5, out d6);


            OutMsg2($"线程池最大允许线程数:{d5}\n最小可用线程数:{data3}\n可用辅助线程的数目 : {data1}\n");

image.png

(图1)


image.png

(图2)



结论:

如下面代码,

此问题通过ThreadPool.SetMinThreads() 把最小线程数由8改为最大就可以了。

   int workerThreadsMin, completionPortThreadsMin;
            ThreadPool.GetMinThreads(out workerThreadsMin, out completionPortThreadsMin);
            int workerThreadsMax, completionPortThreadsMax;
            ThreadPool.GetMaxThreads(out workerThreadsMax, out completionPortThreadsMax);

            // Adjust min threads
            ThreadPool.SetMinThreads(workerThreadsMax, completionPortThreadsMin);

可能有人会问,题目说的是task,最后结论为啥整出个线程池的方法ThreadPool.SetMinThreads() ?

因为Task.Factory.StartNew开的线程默认就是投放到线程池内工作的(当然你也可以指定放到Thread中),因此适用ThreadPool.SetMinThreads()方法。



测试源代码下载:


支付2元或购买VIP会员后,才能查看本内容!立即支付升级会员


发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

«    2025年12月    »
1234567
891011121314
15161718192021
22232425262728
293031
控制面板
您好,欢迎到访网站!
  查看权限
网站分类
搜索
最新留言
文章归档
网站收藏
友情链接

Powered By Z-BlogPHP 1.7.3

Copyright www.skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864