【问题标题】:TPL threads countTPL 线程数
【发布时间】:2013-03-14 15:39:53
【问题描述】:

我有一个针对 .NET 4.0 TPL 程序员的问题。 我创建了这个 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。

谢谢!

【问题讨论】:

标签: c# .net multithreading .net-4.0 task-parallel-library


【解决方案1】:

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

如果您要进行真正的工作而不只是休眠,则不会发生这种情况,因为 ThreadPool 会看到线程实际上正在执行工作,而新线程不会加快整体吞吐量。

现在,在这种情况下,您的延续似乎是实际工作的大部分,在这种情况下,您最好完全不做初始任务:

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

    tasksLeftToRun--;
}

但是,由于您似乎正在处理任务“队列”(您有很多任务要创建),您可能需要调查 Parallel 类是否更适合此任务。如果“作品”以某种形式的集合存储,使用Parallel.ForEach甚至PLINQ可能更合适。

【讨论】:

  • 首先,感谢您的快速响应和答案,它现在可以工作(减少线程数)。我不能使用 StartNew,因为在实际执行之前我需要任务的配置。关于线程的实际生命周期 - 我创建的线程可能需要 10 秒到几分钟。用LongRunning可以吗?
  • @MosheDerri “我需要在实际执行之前配置任务”是什么意思?您可以在 StartNew 中指定它。至于长时间运行 - 我不会推荐它,除非你真的需要它。这将导致每个任务使用专用线程,而不是在 ThreadPool 上运行。您将获得 1 个线程/任务(立即),如果这是基于 CPU 的,这可能会使您的处理器过度饱和。
猜你喜欢
  • 1970-01-01
  • 2011-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-27
  • 1970-01-01
  • 1970-01-01
  • 2015-01-19
相关资源
最近更新 更多