другой доступ потока MemoryStream

Существует немного кода, который пишет, что данные к MemoryStream возражают непосредственно в, он - буфер данных путем вызова GetBuffer (). Это также использует и обновляет свойства Position и SetLength () соответственно.

Этот код работает правильно 99,9999% времени. Буквально. Только каждый несколько 100,000's повторений это будет блевать. Определенная проблема состоит в том, что свойство Position MemoryStream внезапно возвращает нуль вместо соответствующего значения.

Однако код был добавлен, что проверки на 0 и выдают исключение, которое включает журнал свойств MemoryStream как Положение и Длина в отдельном методе. Они возвращают правильное значение. Дальнейшее добавление входа в рамках того же метода показывает, что, когда это редкое условие происходит, Положение только имеет нуль в этом конкретном методе.

Хорошо. Очевидно, это должно быть проблемой поточной обработки. И скорее всего проблема компиляторной оптимизации.

Однако природа этого программного обеспечения - то, что оно организовано "задачами" с планировщиком и таким образом, любой из нескольких фактических потоков O/S может работать, этот код в любом дают время - но никогда, чем по одному.

Таким образом, это - мое предположение, что обычно это так происходит, что тот же поток продолжает привыкать для этого метода, и затем в редком случае другой поток привыкает. (Просто кодируйте идею протестировать эту теорию путем получения и сравнения идентификатора потока.)

Затем из-за оптимизации компилятора, другой поток никогда не получает правильное значение. Это получает "устаревшее" значение.

Обычно в такой ситуации я применял бы "энергозависимое" ключевое слово к рассматриваемой переменной, чтобы видеть, фиксирует ли это ее. Но в этом случае переменные в объекте MemoryStream.

У кого-либо есть какая-либо другая идея? Или это означает, что мы должны реализовать наш собственный объект MemoryStream?

С уважением, Wayne

Править: Просто запустил тест, который считает общее количество вызовов к этому методу и считает количество раз, ManagedThreadId отличается, чем последняя возможность. Это - почти точно 50% времени, когда это переключает потоки - чередующийся между ними. Таким образом, моя теория выше является почти наверняка неправильной, или ошибка происходила бы намного чаще.

Править: Эта ошибка происходит так редко, что потребовалось бы почти неделя для выполнения без ошибки прежде, чем чувствовать любую уверенность, это действительно пошло. Вместо этого лучше выполнить эксперименты для подтверждения точно природы проблемы.

Править: Блокировка в настоящее время обрабатывается через блокировку () операторы в каждом из 5 методов, которые используют MemoryStream.

6
задан Wayne 13 May 2010 в 13:54
поделиться

1 ответ

(Для подтверждения этого действительно нужен примерный код. )

Элементы MemoryStream не задокументированы как потокобезопасные (например, Position ), поэтому вам необходимо убедиться, что вы имеете доступ только к этому экземпляру (или любой ссылке на объект, логически являющейся частью ] MemoryStream ) из одного потока за раз.

Но MemoryStream не задокументирован как имеющий сходство потоков, поэтому вы можете получить доступ к экземпляру из другого потока, если такой доступ не является параллельным.

Многопоточность - это сложно (аксиома для этого вопроса и ответа).

Я бы посоветовал вам иметь некоторый параллельный доступ, когда два потока одновременно обращаются к одному и тому же экземпляру, и это иногда нарушает некоторые аспекты состояния экземпляра.

Я бы позаботился о том, чтобы блокировка была как можно более простой (попытка быть более умной, и ограничение блокировки часто является причиной очень трудного поиска ошибок) и заставляю все работать. Также может помочь тестирование на многоядерной системе.Попытайтесь оптимизировать блокировку только в том случае, если профилирование показывает, что существует потенциал для значительного чистого выигрыша (для приложения в целом).

5
ответ дан 17 December 2019 в 04:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: