У меня есть класс, который представляет «состояние мира». Класс имеет много коллекций многих других объектов, которые, в свою очередь, имеют ссылки на большее количество объектов и коллекций объектов, иногда даже ссылок на своих предков в «мировой иерархии». Для того, чтобы упростить то, что, как говорится, вот пример (преобразуется в XML, детали опущены):Блокировка иерархии объектов в .NET
<World>
<Country>
<City>
<Block>
...
</Block>
</City>
<City>
<Block>
...
</Block>
</City>
</Country>
...
<Country>
<City>
<Block> ... </Block>
...
<Block> ... </Block>
</City>
<City>
<Block> ... </Block>
</City>
</Country>
</World>
Есть два потока, поток UI и фоновый поток (который на самом деле сервер).
Сервер получает сообщения, которые изменяют «состояние мира» (добавление городов, блоков и т. Д.).
Нить пользовательского интерфейса рисует состояние мира, чтобы отображать с помощью объекта PictureBox раз в то время. Уровень представления содержит только ссылку на объект IWorld (который реализует World), и он не имеет доступа к элементам внутри.
Нить UI должна зафиксировать полностью состояние мира, так что мир не может быть изменен (сервером) во время рисования (что сделало бы несогласованную картину мира). Поскольку он имеет только ссылку на объект IWorld, это единственное, что нужно заблокировать.
Мой вопрос заключается в том, достаточно ли этой блокировки (т. Е. Блокировать все поля и свойства, которые этот объект имеет, рекурсивно), или каждый объект должен блокироваться отдельно. Каков правильный подход к этой проблеме?
Примечание: Пользовательский интерфейс не имеет возможности связаться с сервером (это означает, что он не может сказать серверу прекратить изменять мир, а затем сказать ему возобновить после рендеринга).
EDIT: Если мир и все классы в иерархию реализации интерфейса ILock, который обеспечивает блокировку() метод, который бы назвал блокировку() на всех нижних уровнях (рекурсивно), то это, вероятно, будет склонен к тупиковой ситуации (циклические ссылки) или просто слишком дорого.
Я думаю, что изменение конструкции в порядке.
Несмотря на то, что это не дает однозначного ответа на вопрос, оно дает хороший смысл в необходимости изменения дизайна (и довольно легко реализовать). Благодарю. –
Я не вижу, как он не отвечает на вопрос: первое предложение отвечает на это, подумал я. Самый простой способ обеспечить взаимное исключение для всего мира - это просто сделать блокировку обоих потоков одной и той же ссылкой. –
В некотором смысле это не так: Очевидно, что если два объекта пытаются заблокировать одну и ту же ссылку, этого достаточно, чтобы обеспечить взаимную эксклюзивность. Но мой вопрос был на самом деле достаточно ли, если один объект блокирует объекты верхнего уровня, а другой объект блокирует объект нижнего уровня. Но теперь, когда я думаю об этом, это было бы бессмысленно. ОС должна была бы заблокировать все ссылки на объекты, и это создало бы тупик при обнаружении первой циклической ссылки. Так что, наверное, мой вопрос не был точно продуман во-первых. –