1

I am stress testing my application and have written a simple test to spawn hundreds of threads that call a method. The code below works fine for 1000 threads and 100 ms delay.

In the code below when the number of threads is 2000 and the delay is 100 i get the error Cannot load the "shell32.dll" DLL into memory in the catch statement for radButtonEmptyThread_Click

  1. How do i fix this?
  2. The value written "Debug.Print(count.ToString());" is always 1000 - why?

C# Code

private void radButtonEmptyThread_Click(object sender, EventArgs e)
        {
            try
            {

                for (int i = 0; i < int.Parse(radTextBoxWaitThreads.Text); i++)
                {
                    Thread Trd = new Thread(() => EmptyThreadRequest(int.Parse(radTextBoxFloodDelay.Text), i));
                    Trd.IsBackground = true;
                    Trd.Start();
                }
            }
            catch (Exception ex)
            {

                MessageBox.Show(ex.Message.ToString());

            }
        }

        private void EmptyThreadRequest(int delay, int count)
        {

            try
            {

                System.Threading.Thread.Sleep(delay);
                Debug.Print(count.ToString());


            }

            catch (Exception ex)
            {

                MessageBox.Show(ex.Message.ToString());

            }
        }

    }
user1438082
  • 2,740
  • 10
  • 48
  • 82

3 Answers3

2
  1. Stop creating so many threads. That's very resource-intensive. Instead, use Tasks.

  2. i is a captured variable, which means the threads all access the original variable, not a copy. If you create a copy of the variable inside the loop, it will work as expected.

Community
  • 1
  • 1
Kendall Frey
  • 43,130
  • 20
  • 110
  • 148
  • 1
    @Ameen I'm guessing it's because the OS can't handle that many threads at once. – Kendall Frey Feb 09 '13 at 22:19
  • if i use tasks will i not get the error - what about Ameens very valid question? 2. makes sense but what is the solution here? – user1438082 Feb 09 '13 at 22:20
  • I don't think Tasks will cause a problem. They use pooled threads. – Kendall Frey Feb 09 '13 at 22:21
  • only one way to find out. ill report back - what about item 2.? – user1438082 Feb 09 '13 at 22:22
  • Edited. Also, see the linked question. – Kendall Frey Feb 09 '13 at 22:22
  • 1
    @KendallFrey, that's my guess too, but I would have liked to see some explanation as to how in the hell that would translate into a module load error. user1438082, you can also use Thread.QueueUserWorkItem and that would also be a lot more efficient than creating a new thread for every single call. – Ameen Feb 09 '13 at 22:23
  • 1
    I doubt I'll be able to explain it much better, since I didn't write Windows, and am not an expert on how it handles threads. – Kendall Frey Feb 09 '13 at 22:25
  • hi, see my answer posted for 1. - is this ok? it works for 40000 threads and a delay of 100 ms - i noticed the number of threads it creates in the resource monitor does not go above 41 - the original post was at ~1100. make sense? – user1438082 Feb 09 '13 at 22:44
1

To deal with the captured variable issue, inside the loop do this:

int x = i;
Thread Trd = new Thread(() => EmptyThreadRequest(int.Parse(radTextBoxFloodDelay.Text), x));

And of course, consider using Tasks.

2000 is a functional limit enforced by Windows. I think it might have something to do with minimum stack allocated to each thread, but I would not bet my life on it. Tasks are very light weight threads, prefer them over threads when possible.

John
  • 633
  • 4
  • 9
-1

C# Code

private void radButtonCallEmptyTasks_Click(object sender, EventArgs e)
{
    try
    {

        for (int i = 0; i < int.Parse(radTextBoxWaitThreads.Text); i++)
        {

            // Create a task and supply a user delegate by using a lambda expression. 
            var taskA = new Task(() => EmptyTaskRequest(int.Parse(radTextBoxFloodDelay.Text), i));
            // Start the task.
            taskA.Start();
        }
    }
    catch (Exception ex)
    {

        MessageBox.Show(ex.Message.ToString());

    }
}



private void EmptyTaskRequest(int delay, int count)
{

    try
    {

        System.Threading.Thread.Sleep(delay);
        Debug.Print(count.ToString());


    }

    catch (Exception ex)
    {

        MessageBox.Show(ex.Message.ToString());

    }
}

}

user1438082
  • 2,740
  • 10
  • 48
  • 82