Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Unexpected result when accessing main thread variable in loop created child threads

I am writing a program that reads a large amount of dynamic data. I would like to use multi-threading to speed this process up. I understand that it is up to the operating system on how to handle created threads (thread priority, etc), which I believe is the reason for my unexpected results, however, I still do not know a solution.

Code:

int multiplier = rowCount / 20;

Debug.WriteLine("Row count is " + rowCount + "...");
Debug.WriteLine("Using 20 threads to complete job...");
Debug.WriteLine("Using " + multiplier + " as multiplier...");

for (int i = 1; i <= 20; i++) {
    new Thread(() => {
        int startRow = ((multiplier * i) - multiplier) + 1;
        int endRow = multiplier * i;
        
        if (i == 20) {
            endRow = rowCount;
        }
    
        Debug.WriteLine("    [THREAD " + i + "] start row: " + startRow + ", end row : " + endRow);

        for (int row = startRow; row <= endRow; row++) {
            for (int column = 1; column <= columnCount; column++) {
                //...data is read here
            }
        }
    }).Start();
}

Actual result (it appears that my issue is the child thread not "reading" the ‘i’ variable "correctly", which makes sense considering how threads work, I just do not know how to fix it):

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Row count is 2209...
Using 20 threads to complete job...
Using 110 as multiplier...
    [THREAD 4] start row: 331, end row : 440
    [THREAD 4] start row: 331, end row : 440
    [THREAD 5] start row: 441, end row : 550
    [THREAD 5] start row: 441, end row : 550
    [THREAD 6] start row: 551, end row : 660
    [THREAD 7] start row: 661, end row : 770
    [THREAD 9] start row: 881, end row : 990
    [THREAD 9] start row: 881, end row : 990
    [THREAD 11] start row: 1101, end row : 1210
    [THREAD 11] start row: 1101, end row : 1210
    [THREAD 12] start row: 1211, end row : 1320
    [THREAD 14] start row: 1431, end row : 1540
    [THREAD 15] start row: 1541, end row : 1650
    [THREAD 15] start row: 1541, end row : 1650
    [THREAD 16] start row: 1651, end row : 1760
    [THREAD 17] start row: 1761, end row : 1870
    [THREAD 19] start row: 1981, end row : 2090
    [THREAD 20] start row: 2091, end row : 2209
    [THREAD 20] start row: 2091, end row : 2209
    [THREAD 21] start row: 2201, end row : 2310

Expected result (this is the result of simply not using threads, meaning commenting out the lambda expression):

Row count is 2209...
Using 20 threads to complete job...
Using 110 as multiplier...
    [THREAD 1] start row: 1, end row : 110
    [THREAD 2] start row: 111, end row : 220
    [THREAD 3] start row: 221, end row : 330
    [THREAD 4] start row: 331, end row : 440
    [THREAD 5] start row: 441, end row : 550
    [THREAD 6] start row: 551, end row : 660
    [THREAD 7] start row: 661, end row : 770
    [THREAD 8] start row: 771, end row : 880
    [THREAD 9] start row: 881, end row : 990
    [THREAD 10] start row: 991, end row : 1100
    [THREAD 11] start row: 1101, end row : 1210
    [THREAD 12] start row: 1211, end row : 1320
    [THREAD 13] start row: 1321, end row : 1430
    [THREAD 14] start row: 1431, end row : 1540
    [THREAD 15] start row: 1541, end row : 1650
    [THREAD 16] start row: 1651, end row : 1760
    [THREAD 17] start row: 1761, end row : 1870
    [THREAD 18] start row: 1871, end row : 1980
    [THREAD 19] start row: 1981, end row : 2090
    [THREAD 20] start row: 2091, end row : 2209

>Solution :

Try moving the variables that can be calculated outside of the thread to avoid reading the shared variable i in the thread. The threads are started without care of the surrounding loop which increments i.

int multiplier = rowCount / 20;

Debug.WriteLine("Row count is " + rowCount + "...");
Debug.WriteLine("Using 20 threads to complete job...");
Debug.WriteLine("Using " + multiplier + " as multiplier...");

for (int i = 1; i <= 20; i++) {
    int startRow = ((multiplier * i) - multiplier) + 1;
    int endRow = multiplier * i;
    if (i == 20) {
       endRow = rowCount;
    }
    int nThread = i;
    new Thread(() => {
        Debug.WriteLine("    [THREAD " + nThread + "] start row: " + startRow + ", end row : " + endRow);

        for (int row = startRow; row <= endRow; row++) {
            for (int column = 1; column <= columnCount; column++) {
                //...data is read here
            }
        }
    }).Start();
}

It is apparent in the first log you shared, for example when thread 1 and 2 starts, i is already at 4.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading