2014-11-25 37 views
0

“N”线程同时工作TPL我观察到的一个问题内存中变疯了。我想明白为什么我们有这样的行为。为什么如果通过第三方物流创造了的EventWaitHandle

这是一个简单的示例代码。假设我们有一个生产者在产生数据时发出信号。在这个方法中,我们创建了'N'个消费者。

public void StartMultiConsumers() 
{ 
    //// main processor thread.. 

    while (true) 
    { 
     Task.Factory.StartNew(() => 
     { 
      wh.WaitOne(); // causes the memory to grow crazy high 
      wh.Reset(); 
     }); 
    } 
} 

我知道我们可以改进代码,以便我们不创建无限数量的线程。但是由于TPL只能创建少量的线程。为什么我们有这样的行为。

w.WaitOne()导致内存增长的疯狂高。但为什么?

回答

3

即得到由应用程序创建的每个线程,消耗资源的操作系统。你有一个紧密循环简单地旋转关闭新任务尽可能快的,并且仅仅依赖于线程池的限制。但是,这不会持续很长时间,因为线程被纺起来受阻,很快线程池注入新的线程入池..

原因内存穗 - 在.NET中创建的每个线程,被分配一个1MB的默认堆栈。也有与线程相关的其他系统资源,但即使有单独1MB,如果分拆1000个线程,你最终消耗1GB内存应用程序,这是做什么都不,但在等待句柄等待


编辑:为了使它显得更加清晰,考虑以下 -

  • 线程1 - 最显着的系统资源,堆栈的1MB分配。举行 ,直到线程为alive(包括阻塞)。
  • 线程2 - 最显着的系统资源,堆栈的1MB分配。直到线程为 存活(包括阻塞)。
  • ...
  • ...
  • 螺纹1000 - 最显着的系统资源,堆栈的1MB分配。持续到线程为alive (包括阻塞)。由1000 活着保持

总内存/阻塞线程 - 在一个最小(只考虑堆栈分配) - 1000MB。即1GB

+0

但是当我检查到任务管理器我很难得到像14线程的数量因此,这意味着,有没有那么多的线程或任务管理器不显示线程是否正确? – 2014-11-25 05:32:10

+0

也不是导致内存高的WaitOne()方法导致内存的线程数。所以如果我评论这条线,尺寸没有太大的变化。 – 2014-11-25 05:33:55

+2

@DJ等待一个不会导致大内存使用率,这是你在线程中做的阻塞调用。你可以用'Thread.Sleep(10000)'代替WaitOne并看到相同的效果。 – 2014-11-25 06:51:34