1
Thread[] t = new Thread[threadCount];
            int m = 0;
            foreach (var thread in t)
            {
                if (m<threadCount)
                {
                    //This one is needed for paintSingleThread as hight of Bitmap
                    int height = parts[m].Height;

                    //this line causes the exception
                    t[m] = new Thread(() => paintSingleThread(parts[m], "Green", height, width));

                    t[m].Start();
                    m++;
                }

            }

parts[] is a BitMap array already filled with bitmap objects. I want to give different members of array for different threads, but sometimes I get IndexOutOfRangeException because m gets too big.It doesn't occur everytime, it's like every other time i run the program. When debugging, every time was smooth and erro never occured. Even with if(m

I'm interested in both the causation of the problem and code changes to avoid this problem.

  • The cause of the problem is that you're running off the end of the array. It's pretty difficult to tell you why, because you've not provided an actual [mcve] that demonstrates the issue. You're using variables that are not declared and populated in the out-of-context code you've posted. You should use the debugger to step through the code to find out where your logic error is that allows it to go past the end. It's most likely happening when you access `parts[m]`, but it's hard to say for sure without the remaining context. – Ken White Dec 21 '19 at 00:13
  • I'm sorry for unprofessional question, it's my first post.I think that other parts of the code are quite irrelevant, as threadCount is and Integer const (in my case 7, but I tried between 2 and 200), and parts[] is BitMap array, which get's filled just fine even with crash. The things that are the main problem is that: 1. Sometimes it works, sometimes it crashes. 2. I put if (m – hopefulcoder Dec 21 '19 at 00:20
  • Sorry. The site requires a [mcve] when asking us to debug code issues, and a [mcve] means that it can be copied and pasted into a test app and compiled. You've omitted relevant portions of the code (as I indicated before), and if all is as you claim in your comment then the problem wouldn't be happening. If you insist on not providing that [mcve], no one can debug it but you. Use the debugger to find your logic error that is allowing you to exceed the limits of the array. – Ken White Dec 21 '19 at 00:26
  • @KenWhite Just because you weren’t able to find the bug in the OP’s code doesn’t mean the question was not good enough, or lacked context. – Soonts Dec 21 '19 at 14:05

1 Answers1

3

This piece of code

() => paintSingleThread(parts[m], "Green", height, width)

captures m variable by reference, not by value. The value of m after your foreach loop completes will be threadCount, which is out of range. Your code sometimes work, when the threads are launched fast enough and m still contains the correct value at the time when the new threads are running your lambda. For the same reason it works in debugger.

Simple way to fix:

var part = parts[ m ];
t[ m ] = new Thread( () => paintSingleThread( part, "Green", height, width ) );

This code will capture part variable into the lambda. Unlike m, part is declared within the body of the loop. Each loop iteration will have different instance of part, and this code should work as you expect.

Here's a similar question.

Soonts
  • 20,079
  • 9
  • 57
  • 130