volatile должно быть достаточно. Из документов:
Модификатор volatile обычно используется для поля, к которому обращается
несколько потоков без использования оператора блокировки для сериализации доступа.
Эффективно сериализует доступ.
Тем не менее, я не думаю, что это проблема
Вы говорите, что тест всегда должен возвращать false, но иногда он возвращает true. Чтобы «знать», он всегда будет возвращать false, тогда все ваши вызовы DoSomething () должны возвращать false. Это правда? Если бы это был стандартный (последовательный) foreach, он всегда выполнялся бы в одном и том же порядке, поэтому, как только вызов DoSomething вернул false, _isSuccessful остается ложным до конца итерации. Когда вы запускаете эту параллель, порядок выходит из окна. В итоге вы получаете порядок выполнения, который может отличаться каждый раз. Это усугубляется тем фактом, что ваши вызовы DoSomething, вероятно, имеют разное время завершения и могут каждый раз выполняться в разном порядке. Ваши результаты могут быть неповторяемыми и непоследовательными.
Я предполагаю, что вы действительно хотите IsSuccessuful, который верен, только если все DoSomething возвращают true. Один из способов сделать это - удалить && и использовать простое выражение if. Например:
public bool Get()
{
var good = true;
Parallel.ForEach(..., ... =>
{
var result = DoSomething();
if (result == false)
{
good = false;
}
});
IsSuccesful = good;
return IsSuccesful;
}
Как только «хороший» становится ложным, нет способа вернуть его в значение «истина». Следовательно, если один тест возвращает значение false, то IsSuccessful вернет значение false. Это также может прояснить смысл вашего кода для будущих разработчиков, которые с ним работают.