C# TPL线程数

C# TPL线程数,c#,.net,multithreading,.net-4.0,task-parallel-library,C#,.net,Multithreading,.net 4.0,Task Parallel Library,我有一个问题要问.NET4.0TPL程序员。 我创建了这个TPL和ThreadPool压力测试仪,在这里我运行X个测试,每个测试执行Y个任务,完成后,它将继续进行下一个测试 我遇到的问题是,如果一个测试启动100个任务,接下来的测试将添加更多任务,如此类推,给我留下大量的线程 (我的线程数取自资源监视器) 伪代码: while (tasksLeftToRun != 0) { var nextTask = new Task(new Action(()=> {

我有一个问题要问.NET4.0TPL程序员。 我创建了这个TPL和ThreadPool压力测试仪,在这里我运行X个测试,每个测试执行Y个任务,完成后,它将继续进行下一个测试

我遇到的问题是,如果一个测试启动100个任务,接下来的测试将添加更多任务,如此类推,给我留下大量的线程

(我的线程数取自资源监视器)

伪代码:

while (tasksLeftToRun != 0)
{
    var nextTask = new Task(new Action(()=>
    {
        Thread.Sleep(20);
    }), cancellationToken);

    nextTask.Start();
    nextTask.ContinueWith((t) =>
    {
        //...
    },TaskScheduler.Default);
    tasksLeftToRun--;
}
应用程序完成测试约15秒后,线程数降至~7


谢谢

问题在于您使用的是
Thread.Sleep
而不是实际工作,因此线程池会看到您已阻止线程,并开始注入新线程。这将导致线程数随时间增长

如果您要做真正的工作,而不是仅仅睡觉,这将不会发生,因为线程池将看到线程实际上正在执行工作,而新线程将不会提高总体吞吐量

现在,在这种情况下,您的继续工作似乎是实际工作的主要部分,在这种情况下,您最好完全不用最初的任务:

while (tasksLeftToRun != 0)
{
    var nextTask = new Task.Factory.StartNew(()=>
    {
        //... Actual work
    }), cancellationToken);

    tasksLeftToRun--;
}

但是,由于您似乎正在处理一个任务“队列”(要创建的任务太多),您可能需要研究
并行类是否更适合此任务。如果“工作”以某种形式存储在集合中,则使用
Parallel.ForEach
甚至PLINQ可能更合适。

首先,感谢您的快速响应和回答,它现在正在工作(减少线程数)。我不能使用StartNew,因为我需要在实际执行之前对任务进行配置。关于线程的实际生存期-我创建的线程可能需要10秒甚至几分钟。使用LongRunning可以吗?@MosheDerri“在实际执行之前我需要任务的配置”是什么意思?您可以在StartNew中指定这一点。至于长跑,我不推荐,除非你真的需要。这将导致每个任务使用专用线程,而不是在线程池上运行。您将(立即)得到1个线程/任务,如果这是基于CPU的,则可能会使处理器过度饱和