You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

关于Task.Factory.StartNew线程池归还及队列任务检查的技术疑问

嘿,让我逐个拆解你的问题:

问题1:Task.Factory.StartNew()执行完毕后是否会将线程归还至线程池?

默认情况下,当你用Task.Factory.StartNew()且不指定特殊创建选项时,任务会交给线程池调度器处理。一旦任务的委托代码执行完毕,对应的线程池线程就会被归还到线程池,等着被后续任务复用。

不过有个例外:如果你指定了TaskCreationOptions.LongRunning参数,CLR会专门创建一个非线程池的独立线程来跑这个任务。这种情况下,线程在任务结束后会直接被销毁,不会回到线程池。

问题2:如下代码实现中,因Task.Factory.StartNew包含带有Thread.Sleep的while(true)循环,线程是否永远不会归还线程池?该判断是否正确?

这个判断完全正确

道理很简单:线程(不管是线程池线程还是LongRunning的独立线程)会被绑定到这个任务,直到任务彻底执行完成。而你的代码里是while(true)的无限循环——哪怕有Thread.Sleep,也只是让线程暂时休眠,并没有终止任务的运行。只要这个循环不退出,任务就会一直处于“运行中”状态,对应的线程就会被一直占用,根本没机会归还线程池(如果是线程池线程),也不会被销毁(如果是独立线程),直到整个进程终止。

问题3:如何检查队列中是否有待执行的任务?

这得看你用的队列具体是怎么实现的,结合你代码里的PlayWithQueue类,给你几个实用方案:

  • 给自定义队列加状态属性:如果PlayWithQueue是你自己写的,直接给它加个公开属性来暴露队列状态就行,比如用ConcurrentQueue的话:

    public class PlayWithQueue
    {
        private readonly ConcurrentQueue<Action> _taskQueue = new ConcurrentQueue<Action>();
        
        // 你的AddToQueueForExecution方法...
        
        // 检查是否有待执行任务
        public bool HasPendingTasks => !_taskQueue.IsEmpty;
        // 或者想知道具体数量:public int PendingTaskCount => _taskQueue.Count;
    }
    

    之后你就可以通过s.HasPendingTasks轻松判断了。

  • 用队列自身的方法判断:如果用的是ConcurrentQueue这类线程安全队列,也可以调用TryPeek(out _)——如果返回true,就说明队列里还有待处理的任务:

    // 假设_taskQueue是PlayWithQueue里的私有队列,你可以封装成方法或者暴露出来
    if (s._taskQueue.TryPeek(out _))
    {
        // 存在待执行任务
    }
    
  • 如果是线程池的任务队列:很遗憾,.NET没有公开直接访问线程池内部队列的API。这种情况下你要么自定义TaskScheduler来跟踪任务,要么用系统性能计数器(比如“ThreadPool Queue Length”)来间接查看队列长度。


附上你提供的代码片段:

namespace ConsoleApplication1 {
    class Program {
        static void Main(string[] args) {
            Helper h = new Helper();
            PlayWithQueue s = new PlayWithQueue();
            s.AddToQueueForExecution(() => { h.Indicate(1); });
            s.AddToQueueForExecution(() => { h.Indicate(2); });
            s.AddToQueueForExecution(() => { h...
        }
    }
}

内容的提问来源于stack exchange,提问作者A191919

火山引擎 最新活动