views:

93

answers:

3

I have a problem with multithreading in .net. With the following code:

class Program
{
    private static ManualResetEvent[] resetEvents;

    private void cs(object o)
    {
        int xx = 0;
        while (true)
        {
            xx++;
            System.Xml.XmlDocument document = new System.Xml.XmlDocument();
            document.Load("ConsoleApplication6.exe.config");

            MSScriptControl.ScriptControlClass s = 
                newMSScriptControl.ScriptControlClass();
            s.Language = "JScript";
            object res = s.Eval("1+2");
            Console.WriteLine("thread {0} execution {1}" , o , xx);
            System.Threading.Thread.Sleep(5000);
        }

    }
    static void Main(string[] args)
    {
        Program c = new Program();
        for (int i = 0; i < 1000; i++)
        {
            System.Threading.Thread t = new System.Threading.Thread(
                new System.Threading.ParameterizedThreadStart(c.cs));
            t.Start((object)i);
        }
    }
}

When this code executed, it crashes after some minutes. Why is it crashing? What can I do to prevent the crashes?

+2  A: 

You're starting 1000 threads. That is 1000 MB in stack space alone plus all the objects the threads create. My guess is that you're running out of memory. What are you trying to accomplish?

Brian Rasmussen
@Brian: Wow. He's actually created a StackOverFlow the easy way :)
Joel Etherton
@Joel: I doubt that the OP is getting a StackOverflowException as the code is not exhausting the stack. It could be OutOfMemoryException.
Brian Rasmussen
How do you figure out the 1000 MB in stack space? I count (4 (`o`) + 4 (`xx`) + 4 (`document`) + 4 (`s`) + 4 (`res`) + 4 (return address)) * 1000 bytes = 6 KB.
Konrad Rudolph
@Konrad: Each thread has a stack of 1 MB per default in .NET (unless its an ASP application in which case the default is 256 kb). The code creates 1000 threads so the process reserves space for 1000 MB of stacks.
Brian Rasmussen
@Konrad, that is because each thread by default has a 1 MB stack, and there is 1000 of them.
driis
i write a voip based software. in my software there is one thread for each channel.this thread must handle an activex object (msscript.ocx) in loop. when i execute this software the handle count increase continusly and size of virtual memory too. i think that the created object was not dispose.
saeed
@saeed: Judging from the code above, your code launches a number of threads, that never finish so obviously whatever space they use are never reclaimed. If you need to run a lot of small tasks you're probably much better off using the Threadpool as firing up threads can be quite expensive.
Brian Rasmussen
the threadpool is good idea but i want to create 1000 thread immidiatly. threadpool creates thread slowly
saeed
@saeed: Why do you want 1000 threads? Most likely you will just be wasting a lot of cycles on context switches.
Brian Rasmussen
because i have 1000 channel. i must execute a jscript (msscript.ocx) in loop. this cause to handle count increased. i used marshal.releaseComObject to release com object but it not worked.is exist better way?
saeed
@Saeed: unless you have a 1000 CPUs you're not going to process the 1000 channels concurrently anyway. Why don't you spin up a limited number of threads and have them each do a little processing per channel.
Brian Rasmussen
i found problem. it is that when i create n number of msscript obejct then i can not create more object and this cause to process downed.i think msscript has problem.
saeed
Well, as I said my guess was that it was OOM. Spawning 1000 threads will put a significant strain on your address space (assuming you're on 32 bit).
Brian Rasmussen
now i can't resolve this problem.do you know how i resolve this issue?
saeed
You still haven't told us the exception, so it is hard to give specific advice. If my assumptions is correct you're running out of memory. One way to address this is to avoid creating 1000 threads. As I said it will most likely not improve performance and it is using a significant part of the available address space.
Brian Rasmussen
i want to use Microsoft.JScript.Vsa; but i don't khnow it's usage.can you help me?
saeed
When you say the application crashes, I assume you get an error message and a stack trace. What does that say?
Brian Rasmussen
i want to add an c# object to javascript code;
saeed
the vs debugger downed and i cant to see error description.
saeed
A: 

It rarely makes sense to create more threads than processor cores b/c the app will spend alot of time context switching and you will not see much if any performance gain. The only number of threads that will run at the same time equals the number of cores your machine has. Why does this have to be done with 1000 threads? (Obviously I am assuming you don't have a 1000 core machine)

Bobby
A: 

There are probably some aspects of this app that aren't apparent given the provided code. That being said, I haven't been able to reproduce the crash but I am able to run up an obscene amount of memory usage (160MB at 29 "xx++"s).

I suspect that the ScriptControlClass is staying alive in memory. While there may be better ways of solving this problem, I was able to keep the memory at a consistent 60-70MB with this addition:

Console.WriteLine("thread {0} execution {1}" , o , xx);
s = null;

UPDATE
I had similar results with this code memory-wise but the code below was slightly faster. After several minutes the memory usage was a consistent 51MB when xx < 30 was changed back to true.

class Program
{
    private static ManualResetEvent[] resetEvents;

    [ThreadStatic]
    static ScriptControlClass s;

    private void cs(object o)
    {
        int xx = 0;

        if (s == null)
        {
            s = new ScriptControlClass();
        }

        /* you should be able to see consistent memory usage after 30 iterations */
        while (xx < 30)
        {
            xx++;

            //Unsure why this is here but doesn't seem to affect the memory usage
            //  like the ScriptControlClass object.
            System.Xml.XmlDocument document = new System.Xml.XmlDocument();
            document.Load("ConsoleApplication6.exe.config");

            s.Language = "JScript";
            object res = s.Eval("1+2");
            Console.WriteLine("thread {0} execution {1}", o, xx);

            System.Threading.Thread.Sleep(5000);
        }

        s = null;

    }
    static void Main(string[] args)
    {
        Program c = new Program();
        for (int i = 0; i < 1000; i++)
        {
            System.Threading.Thread t = new System.Threading.Thread(
                new System.Threading.ParameterizedThreadStart(c.cs));
            t.Start((object)i);
        }
    }
}

UPDATE 2
My Googling can't find anything about using the ScriptControlClass in a multithreaded environment.

Austin Salonen