Reputation: 838
I have a list containing objects and I wish to run operations against each list item in parallel. One of those operations involves modifying a property of the object. I thought that shouldn't cause an issue thread-safety wise, but my unit test is failing randomly, so I'm worried there is a race condition.
The exact failure case is that the test will fail saying that the list is empty, but only if I run my my test regularly, if I run in debug mode the problem disappears. None of my code should be removing/adding elements, the list is generated at the start and then never directly modified, only the elements themselves are modified.
Is modifying properties on classes in a C# list threadsafe?
Here is the code in question:
List<ExampleObject> localApplications = MethodThatProducesTheList();
Parallel.ForEach(localApplications, localitem =>
{
if (localitem.BuildLabel.Contains("_Release_"))
{
// Delete applications from the old system
var appToDelete = Path.Combine(AppRootPath, localitem.Name, localitem.BuildLabel);
DeleteDirectory(appToDelete);
}
else
{
var st = MethodThatGetsTheState(localitem.BuildLabel);
localitem.State.Add(st);
}
});
Here is a more minimal example:
var object = new {
prop = "foo"
};
var list = new[] { object }.ToList();
Parallel.ForEach(list, listItem =>
{
listItem.prop = "bar";
});
if (list[0].prop != "bar") {
Assert.Fail()
}
Upvotes: 1
Views: 1243
Reputation: 838
Alright, so the issue causing my problem wasn't a race case in the ForEach, but instead the combination of a timing issue and a singleton being shared in the test environment.
However, my original question was simply whether it was safe to use a C# list across threads assuming that the operations carried out with each list element were themselves threadsafe. In other words, is using Parallel.ForEach on a List just as thread safe/unsafe as doing a similar operation on an array. From the comments of users here, it appears the answer is yes.
Namely, that so far as thread safety goes a List can be considered equivalent to an array assuming the user isn't adding or removing elements from the list, sorting the list, etc.
Upvotes: 2