Я могу ошибаться, но мне кажется, что вы идете не с того конца.
Есть две разные проблемы, которые вам нужно решить.
Во-первых, убедитесь, что PropertyGrid доступен только в потоке пользовательского интерфейса. Если какой-либо из его методов (включая свойство getter / setters) доступен из других потоков, вы будете страдать загадочным образом. Исключение составляют, конечно, InvokeRequired()
и Invoke
.
Во-вторых, убедитесь, что поисковая цепочка может работать правильно.
Чтобы решить первую проблему, либо убедитесь, что ваши объекты никогда не изменяются , за исключением потоком пользовательского интерфейса, или делают все ваши триггеры событий осведомленными о потоке так что события ваших объектов (например, PropertyChanged) запускаются только в потоке пользовательского интерфейса.
Вторая проблема проще - если ваша поисковая цепочка ЧИТАЕТ только ваши основные объекты, все должно работать нормально. Да, ваша поисковая цепочка может случайно увидеть некоторые частично обновленные данные, но действительно ли это проблема?
Пара заключительных мыслей ...
Не реализуйте свой поиск для перебора самой PropertyGrid; получить список объектов заранее (они не должны быть клонами) и проработать это вместо этого.
Рассматривали ли вы использование Idle Processing для поиска? Объект Application
запускает событие каждый раз, когда в приложении заканчиваются сообщения для обработки - вы можете подключиться к нему и выполнять 1 шаг поиска при каждом запуске события. Что-то вроде потока бедняков, но без головной боли mutex / lock / semaphone. Я использовал это для очень хорошего эффекта в прошлом.
Обновление : Если я правильно помню, PropertyGrid учитывает интерфейс IEditableObject
, вызывая BeginEdit
, как только вы начнете изменять строку, и EndEdit
при переходе в другой ряд. Вы можете использовать это, чтобы в поисковой цепочке не отображались неполные изменения.
Обновление 2 : В результате я обнаружил, что вы уже знали - PropertyGrid не не поддерживает интерфейс IEditableObject.
У меня есть еще одно предложение - хотя это может быть больше работы, чем вы хотите инвестировать.
Примерно в то время, когда в .NET 2.0 было представлено пространство имен System.Transactions, я увидел статью об использовании внешней транзакции для обеспечения изоляции потоков для объектов. Идея состоит в том, что свойства вашего объекта имеют двойное хранилище. Сначала у вас есть зафиксированное значение, видимое для всех потоков, и у вас есть локальная переменная потока, используемая для хранения незафиксированных значений для каждого потока. Когда свойство модифицируется, объект включается в любую внешнюю транзакцию, сохраняя новое значение в локальном потоке. Когда транзакция фиксируется или откатывается, значение для потока либо сохраняется, либо отбрасывается.
К сожалению, я не могу найти оригинальную статью, хотя кажется, что CSLA предоставляет эту поддержку. Надеюсь, это поможет.