Кажется, я нашел ответ и в процессе тоже вопрос.
Реальный вопрос заключался в том, можно ли доверять локальным «переменным», которые на самом деле являются объектами, для одновременного доступа. Ответ - нет, если они имеют внутреннее состояние, которое не обрабатывается потокобезопасным способом, все ставки отключены. Закрытие не помогает, оно просто захватывает ссылку на указанный объект.
В моем конкретном случае - одновременное чтение из IEnumerable<T>
и отсутствие записи в него, является на самом деле потокобезопасным, поскольку каждый вызов foreach
, Contains()
, Where()
и т. Д. получает новый IEnumerator
, который виден только из потока, который его запросил. Любые другие объекты, однако, также должны быть проверены, один за другим.
Итак, ура, никаких блокировок или синхронизированных коллекций для меня:)
Благодаря @ebb и @Dave, хотя вы не ответили на вопрос напрямую, вы указали мне правильное направление.
Если вас интересуют результаты, это запуск на моем домашнем ПК (четырехъядерный процессор) с Thread.SpinWait
для имитации времени обработки строки. Реальное приложение улучшилось почти в 2 раза (01:03 против 00:34) на двухъядерной гиперпоточной машине с SQL Server в локальной сети.
Однопоточный, с использованием foreach
. Я не знаю почему, но количество переключателей контекста ядра довольно велико.
Использование Parallel.ForEach
, без блокировки с локальными потоками, где это необходимо.