0

When I run the next code, an OutOfMemoryException is thrown:

static void Main(string[] args)
{
    for (int i = 0; i < 200; i++)
    {
        Stream filestream = new MemoryStream(Resources.File); // Resources.File is typeof byte[]
        ThreadPool.QueueUserWorkItem(ThreadProc, filestream);
    }
    Thread.Sleep(999999999);
}

private static void ThreadProc(object stream)
{
    // Document is 3rd party's class
    Document doc = new Document((Stream)stream); // OutOfMemoryException is thrown after 160 iterations
}

But, if I create the Stream inside "ThreadProc" method - there is no exception:

static void Main(string[] args)
{
    for (int i = 0; i < 200; i++)
    {
        ThreadPool.QueueUserWorkItem(ThreadProc, null);
    }
    Thread.Sleep(999999999);
}

private static void ThreadProc(object stream)
{
    Stream filestream = new MemoryStream(Resources.File);
    Document doc = new Document(filestream); // Exception is NOT thrown
}

Why is there a difference?

Roi Bar
  • 105
  • 11
  • `ThreadProc` only executes when a thread is available, so the memory stream only is created less frequently, allowing the garbage collector to free up more contiguous memory. – user1666620 Feb 29 '16 at 16:19
  • Well, for one, in the second case the rate at which you create those memory streams is limited by the amount of worker threads you have running, and as soon as the stream is processed, it is eligible for garbage collection. In the first case, you first create all the streams, and *process* them over time, which means you have ~200 streams open at the same time, inelligible for garbage collection. That said, the `MemoryStream` shouldn't really be something expensive - `Resources.File` might be the culprit instead, hidden inside the `MemoryStream`. – Luaan Feb 29 '16 at 16:19
  • This code does not behave the same when you run the Debug build or have a debugger attached. Nothing to do with threads, moving the code into another method is enough. Backgrounder [is here](http://stackoverflow.com/a/17131389/17034). – Hans Passant Feb 29 '16 at 16:23

1 Answers1

6

because the first one allocates all the memorystreams in the loop, always.

The seond one only allocates them as the threads run. Since you run in the thread pool they are not run all at once

pm100
  • 48,078
  • 23
  • 82
  • 145