Изменение объекта запустившего событие Modified

Автор Тема: Изменение объекта запустившего событие Modified  (Прочитано 198 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

Оффлайн KazikinАвтор темы

  • ADN OPEN
  • Сообщений: 7
  • Карма: 0
Добрый день!

Тут https://sites.google.com/site/bushmansnetlaboratory/translate-manual/ispolzovanie-sobytij/rekomendacii-otnositelno-obrabotcikov-sobytij черным по белому написано:
Цитировать
Вы можете записать данные любого объекта в базу данных, но избегайте изменять объект, который вызвал событие.
    Очевидно, что любой объект вызвавший событие, может быть в настоящее время еще открыт и над ним может происходить какое либо действие. По этому избегайте изменений этого объекта из обработчика событий. Тем не менее вы смело можете считать информацию из объекта, который запустил событие.

Есть ли способы по обходу данного запрета?

Опишу задачу, которая встала передо мной. Есть вхождение динамического блока с атрибутом. При изменении параметра дин.блока хочу изменить значение атрибута. Но при Commit(), вываливается ошибка: AccessViolationException. Похоже, что происходит описанное в цитате. Как можно "дождаться" пока объект освободится?

Подскажите, как быть, пожалуйста.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 6152
  • Карма: 644
  • Рыцарь ObjectARX
  • Skype: rivilis
При изменении параметра дин.блока хочу изменить значение атрибута.
Не понятен контекст. Имеется в виду в событии изменения параметра динамического блока? Или ты сам меняешь параметр и сразу же хочешь изменить значение атрибута? Это разные вещи. Короче говоря лучше покажи код.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн KazikinАвтор темы

  • ADN OPEN
  • Сообщений: 7
  • Карма: 0
Хочу чтобы при изменении пользователем геометрических параметров Блока изменялись так же и его атрибуты. И наоборот при изменении значения атрибута - изменялась геометрия.

К вхождению блока цепляю так:
Код - C# [Выбрать]
  1.  br.Modified += new EventHandler(SmoBlockMod);

Код - C# [Выбрать]
  1.         void SmoBlockMod(object senderObj, EventArgs evtArgs)
  2.         {
  3.             Document acDoc = acad.DocumentManager.MdiActiveDocument;
  4.             Database acCurDb = acDoc.Database;
  5.             Editor ed = acDoc.Editor;
  6.  
  7.             if (acCurDb.TransactionManager.NumberOfActiveTransactions == 0)
  8.                 if (senderObj.GetType() == typeof(BlockReference))
  9.                 {
  10.                     BlockReference br = senderObj as BlockReference;
  11.                     using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
  12.                     {
  13.                         double h = 0;
  14.  
  15.                         foreach (DynamicBlockReferenceProperty j in
  16.                             br.DynamicBlockReferencePropertyCollection)
  17.                         {
  18.                             if (j.PropertyName == "Высота")
  19.                                 h = Convert.ToDouble(j.Value);
  20.                         }
  21.  
  22.                         foreach (ObjectId attRefID in br.AttributeCollection)
  23.                         {
  24.                             DBObject obj = acTrans.GetObject(attRefID,
  25.                                 OpenMode.ForRead);
  26.  
  27.                             AttributeReference attRef = obj as AttributeReference;
  28.  
  29.                             if (attRef != null)
  30.                                 if (attRef.Tag == "ВЫСОТА")
  31.                                 {
  32.                                     attRef.UpgradeOpen();
  33.                                     attRef.TextString = Convert.ToString(Math.Round(h / 1000, 1));
  34.                                     attRef.DowngradeOpen();
  35.                                 }
  36.                         }
  37.  
  38.                         acTrans.Commit();
  39.                     }
  40.                 }
  41.             ed.Regen();
  42.         }

Оффлайн avc

  • ADN Club
  • ***
  • Сообщений: 173
  • Карма: 22
    • Мои плагины к Автокаду
Я думаю, что модифицировать любые объекты по событию модификации - это уже плохая практика. Я предпочитаю просто запоминать ID измененного объекта и делать всю обработку в событии простоя или в doc_CommandEnded.
Конечно тут есть подводные камни: до вызова обработчика может быть модифицированно много объектов, может быть удален объект, может быть изменен несколько раз. И вообще может обработчик не вызваться и данные рассинхронизируются (в этом конкретном случае не будет соответствия параметра и атрибута). Значит доверять данным в атрибуте нельзя.

Оффлайн avc

  • ADN Club
  • ***
  • Сообщений: 173
  • Карма: 22
    • Мои плагины к Автокаду
... и что-то мне кажется вам просто надо в блоке сделать атрибут, отображающий отформатированное значение параметра. Разве это не делается штатными средствами бе з программирования? Я не спец по динамическим блокам, но я б покопал в эту сторону

Отмечено как Решение Kazikin 21-04-2017, 14:50:42

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 6152
  • Карма: 644
  • Рыцарь ObjectARX
  • Skype: rivilis
Kazikin
1. Однозначно Editor.Regen запускать в событии изменения объекта нельзя.
2. Можно попробовать заменить acCurDb.TransactionManager.StartTransaction() на acCurDb.TransactionManager.StartOpenCloseTransaction()
3. avc прав и так делать не следует вообще. Обработка должна осуществляться не в этом событии. В этом событии ты лишь запоминаешь ObjectId примитива, который потом будешь обрабатывать в другом событии.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение