DrawableOverrule.WorldDraw фатальная ошибка при печати командой PLOT

Автор Тема: DrawableOverrule.WorldDraw фатальная ошибка при печати командой PLOT  (Прочитано 7475 раз)

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

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 738
Есть у меня в проекте перерисовка внешнего вида объекта в чертеже с помощью DrawableOverrule. Все отлично работало, но только до того момента, когда этот объект попытались напечатать - AutoCAD стабильно падает с фатальной ошибкой. Отладка показала, что вылет происходит в методе WorldDraw в строке 21 (код основательно упростил, чтобы показать суть):
Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.DatabaseServices;
  2. using Autodesk.AutoCAD.GraphicsInterface;
  3. using System.Collections.Generic;
  4.  
  5. namespace AcadTests
  6. {
  7.     class DrawableOverruleTest : DrawableOverrule
  8.     {
  9.         public override bool WorldDraw(Drawable drawable, WorldDraw wd)
  10.         {
  11.             if (drawable is Entity)
  12.             {
  13.                 Entity drawEnt = drawable as Entity;
  14.  
  15.                 List<Entity> ents = GetOverruleObjectsForEntity(drawEnt);
  16.  
  17.                 foreach (Entity ent in ents)
  18.                 {
  19.                     using (ent)
  20.                     {                        
  21.                         wd.Geometry.Draw(ent);
  22.                     }
  23.                 }
  24.             }
  25.  
  26.             return true;
  27.         }
  28.  
  29.         private List<Entity> GetOverruleObjectsForEntity(Entity ent)
  30.         {
  31.             List<Entity> ret = new List<Entity>();
  32.  
  33.             /// ***
  34.             /// Тут идет код, в котором создаются различные объекты для
  35.             /// отрисовки: отрезки, блоки, тексты, мтексты...
  36.             /// Эти объекты помещаются в список ret
  37.             /// ***
  38.  
  39.             return ret;
  40.         }
  41.     }
  42. }
  43.  
Но, если заменить
Код - C# [Выбрать]
  1. wd.Geometry.Draw(ent);
на
Код - C# [Выбрать]
  1. ent.WorldDraw(wd);
то ошибка пропадает. Опыты показали, что это актуально для созданных для отрисовки блоков, текстов и мультитекстов. Подозреваю, что здесь как-то замешана аннотативность. В чем же разница между этими методами? Я всегда считал, что они идентичны.
« Последнее редактирование: 08-12-2016, 18:21:52 от Дмитрий Загорулькин »

Отмечено как Решение Дмитрий Загорулькин 08-12-2016, 14:44:39

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

  • Administrator
  • *****
  • Сообщений: 13894
  • Карма: 1789
  • Рыцарь ObjectARX
  • Skype: rivilis
Подозреваю, что здесь как-то замешана аннотативность. В чем же разница между этими методами? Я всегда считал, что они идентичны.
Скорее не аннототивность, а тот факт, что объекты могут считываться/модифицироваться между командами в событиях/реакторах самого AutoCAD или вертикальных приложений, т.е. в этот момент они должны существовать.
Проблема в том, что когда происходит непосредственная работа AutoCAD'а с примитивами из List<Entity> ents они могут быть уже очищены (Dispose). Поэтому если хочешь пользоваться методом wd.Geometry.Draw(ent) то нужно обеспечить их неудаляемость. На форуме мы уже это как-то обсуждали в контексте Solid3d.
Ну и есть очень старый пост на сайте ADN: http://adn.autodesk.com/adn/servlet/devnote?siteID=4814862&id=6410837&linkID=4900509
Он касается Custom Entity, но логика такая же самая. Сокращенно смысл в том, что примитивы должны существовать как минимум до окончания регенерации чертежа, которая выполняется в процессе печати.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 738
Вот оно как! Спасибо!
Так что же, получается, что ent.WorldDraw(wd) куда-то сохраняет объект до окончания регенерации?

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

  • Administrator
  • *****
  • Сообщений: 13894
  • Карма: 1789
  • Рыцарь ObjectARX
  • Skype: rivilis
Наоборот. Вызов ent.WorldDraw(wd) не кэшируется, т.е. выполняется непосредственно в момент вызова, а вызов wd.Geometry.Draw(ent) кэшируется и откладывает непосредственную отрисовку на более позднее время, требуя, чтобы ent в это время существовал.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 738
оэтому если хочешь пользоваться методом wd.Geometry.Draw(ent) то нужно обеспечить их неудаляемость.
Вот с этим способом как-то не складывается. Каким образом это можно сделать? Я попробовал сохранять объекты в статический список, но это никак не помогло.

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

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

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 738
Я, честно говоря, не представляю способа, как мне каждый объект отдельно в статическом поле сохранить - их у меня под 200 шт набирается для одного отрисовываемого объекта чертежа... Ну да ладно, способ ent.WorldDraw(wd) работает, вроде, неплохо. На нем и остановлюсь :)