C# 知道线程池何时为空

C# 知道线程池何时为空,c#,multithreading,backgroundworker,threadpool,C#,Multithreading,Backgroundworker,Threadpool,我可以;似乎找不到一种简单的方法来确定线程池何时完成了所有排队的任务。我在这里找到了一些答案,但没有一个能帮到我 为了简单起见,让我们说: for (int i=0;i<10;i++) { threadpool.queueuserworkitem(Go); } void Go() { Console.WriteLine("Hello"); } for(inti=0;i您不会询问线程池,而是让每个后台线程在完成时提供通知 但你自己不要这样做,使用新的TPL和任务类: var

我可以;似乎找不到一种简单的方法来确定线程池何时完成了所有排队的任务。我在这里找到了一些答案,但没有一个能帮到我

为了简单起见,让我们说:

for (int i=0;i<10;i++)
{
   threadpool.queueuserworkitem(Go);

}
void Go()
{
   Console.WriteLine("Hello");
}

for(inti=0;i您不会询问线程池,而是让每个后台线程在完成时提供通知

但你自己不要这样做,使用新的TPL和
任务
类:

var tasks = new Task[10];
for (int i=0;i<10;i++)
{
    tasks[i] = Task.Factory.StartNew( Go );
}

Task.WaitAll(tasks);
Console.WriteLine("All done");

void Go()
{
   Console.WriteLine("Hello");
}
var tasks=新任务[10];

对于(int i=0;i而言,依赖线程池的空性是不可能的,也是危险的。您可以自己计算活动任务。使用monitor的低级方法:

   class Program
    {
        static object _ActiveWorkersLock = new object();
        static int _CountOfActiveWorkers;

        static void Go(object state)
        {
            try
            {
                Console.WriteLine("Hello");
            }
            finally
            {
                lock (_ActiveWorkersLock)
                {
                    --_CountOfActiveWorkers;
                    Monitor.PulseAll(_ActiveWorkersLock);
                }
            }
        }

        static void Main(string[] args)
        {
            for (int i = 0; i < 10; i++)
            {
                lock (_ActiveWorkersLock)
                    ++_CountOfActiveWorkers;
                ThreadPool.QueueUserWorkItem(Go);
            }

            lock (_ActiveWorkersLock)
            {
                while (_CountOfActiveWorkers > 0)
                    Monitor.Wait(_ActiveWorkersLock);
            }

            Console.WriteLine("All done");
        }
    }
类程序
{
静态对象_ActiveWorkersLock=新对象();
活动工作者的静态整数;
静态void Go(对象状态)
{
尝试
{
Console.WriteLine(“你好”);
}
最后
{
锁(_ActiveWorkersLock)
{
--_积极工作者人数;
Monitor.pulsell(_ActiveWorkersLock);
}
}
}
静态void Main(字符串[]参数)
{
对于(int i=0;i<10;i++)
{
锁(_ActiveWorkersLock)
++_积极工作者人数;
ThreadPool.QueueUserWorkItem(Go);
}
锁(_ActiveWorkersLock)
{
而(_CountOfActiveWorkers>0)
Monitor.Wait(_ActiveWorkersLock);
}
控制台。写入线(“全部完成”);
}
}
您是否尝试过使用

Rx使这项工作变得非常简单。例如,您可以这样重写您的问题:

    private void test()
    {
        var list = Enumerable.Range(0, 10)
            .ToObservable()
            .ObserveOn(Scheduler.ThreadPool)
            .SubscribeOn(Scheduler.ThreadPool)
            .Subscribe(i=>Go(),Done);

    }

    void Go()
    {
        Console.WriteLine("Hello");
    }

    void Done()
    {
        Console.WriteLine("Done");
    }

超级简单。看看Rx,你会很高兴它能起作用,但我需要一些东西,我可以排队处理500个任务,一次只能执行10个(仅10个线程),因此其余的线程将排队等待线程释放。还有其他想法吗?任务使用底层线程池。默认线程数基于计算机的CPU计数,但如果您希望通过自定义
任务调度器
对线程数进行显式控制,也可以使用PLINQ和DEGREEOF并行性(10)选项。我在创建自定义TaskScheduler时四处查看,它对我来说似乎有点太高级了。我会看看是否能找到解决方法,如果不能,我会选择Oggre的solution@Darko参见上面的编辑。另一个备选方案是上文建议的PLINQ(它在封面下使用相同的TPL库)。唯一需要注意的是,当它在多个线程上执行工作时,它会阻止调用线程直到完成。因此,如果您希望启动工作的线程继续,您必须将PLINQ查询分派到另一个线程(通常使用任务)这正是我所需要的。只有一个问题,因为我对C有点陌生,在路上会拾起一些零碎的东西-我唯一不能理解的部分是“锁(_ActiveWorkersLock)”,它的整个实现,_ActiveWorkersLock,它的用途是什么?锁(…)是监视器原语,与critical section非常相似。\u ActiveWorkersLock只是一个对象,它用作critical section的ID。Wait和Pulse是等待和发送信号的方法。这使监视器与POSIX中的条件变量有些相似。但所示的方法级别较低,可能很难出错。我建议您坚持使用使用PLINQ和TPL,正如另一个答案中所建议的那样。这些技术也将为您带来正确的异常处理。我强烈建议不要使用这种方法@Darko。任务和TPL为您提供的支持取消、异常处理等的管道比这多得多。@ogggre-如果CountOfActiveWorkers尚未减为零?为什么必须在main()中执行零检查?我认为Rx不适合这种情况。正如您所展示的,虽然这是可能的,但TPL更适合。例如,您将如何取消所有操作?一旦完成,您将如何确定哪个任务引发异常?您会推荐什么资源?请记住,我是beginerRx是专为此设计的。有一个您可以传入的rd参数,在异常发生时执行。您可以使用它来处理和识别异常。要取消操作,
list
的类型为
IDisposable
,只需调用dispose,操作就被取消了。是的,我会在这里观看视频:它们信息量很大我认为您使用Rx作为si别误会,我喜欢Rx,觉得它很漂亮,但对我来说,TPL和PLINQ适合这个场景,并且产生了更容易理解的代码。