Question

I have some code running in my application that calls the method below for multiple students.

The problem is that I use the Student parallel index variable to call another method and using the local variable of that method I insert a message record and save all messages for that Student once.

What happens is sometimes the message inserted into the database has the wrong ownerId sometimes.

For example a message owned by StudentRecord Id 10 is inserted into the DB with owner Id value set as 17 instead of 10. 17 is a studentId in the same class but so it seems to be getting confused with the parallel loop.

For my understanding of the parallel loop everything inside the loop will have its own instance of a local variable so index Student will create its own block of local variables so I don't see how the StudentId is being inserted incorrectly into the Database.

Some bad sharing must be going on. This is not the actual data or variables used. I just tried to simplify as much as possible.

var students = GetAllStudentsForThisClass();
Parallel.ForEach(
    students,
    new ParallelOptions {
        MaxDegreeOfParallelism = 5
    },
    student => {
        var dbThread = new StudentLifeRepository();
        var studentRecord = dbThread.GetStudentById(student.Id);
        var records = new List<Student_Messages>();
        do {
            StudentMessage.Statuses = //web api call, returns null when no Statuses are available from api

            foreach (var studentMessage in StudentMessage.Statuses) {
                var message = new Student_Messages();
                //this is where I think the problem lies
                message.ownerId = studentRecord.StudentId;

                message.CreatedDate = studentMessage.MessageDate;
                message.ID = studentMessage.MessageId;
                message.message = studentMessage.message;

                records.Add(studentMessage);
            }
            //this loop happens until No more messages are available for this student
        } while(StudentMessage.Statuses != null);

        //DistinctItemComparer is making sure All messageIds
        //are unique since that is used for primary key
        foreach (var pt in records.Distinct(new DistinctItemComparer())) {
            dbThread.Add(pt);
            dbThread.Save();
        }
    }  
); //close of parallel loop
Était-ce utile?

La solution

It would appear that you are using a static or externally scoped property: StudentMessage.Statuses from within a thread. This will lead to issues since the static property will be shared between all the threads. When one thread assigns a new value to that property it will effect the other threads.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top