Removing something that wasn't added?

Автор Тема: Removing something that wasn't added?  (Прочитано 8183 раз)

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

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

Оффлайн Алексей ТерноАвтор темы

  • ADN Club
  • ****
  • Сообщений: 381
  • Карма: 33
    • C3D Extensions
  • Skype: alexeyterno
Removing something that wasn't added?
« : 19-04-2019, 11:20:22 »
Прислали мне несколько чертежей для тестирования. При открытия одного из них я получаю вот такое сообщение:

Прервать - закрытие автокада/сивила.
Повтор - отладка в VS.
Пропустить - все загружается и работает, но после закрытия этого чертежа или переключении на другой появляется вот такое сообщение:


В первом сообщении я нашел упоминание события EnteringQuiescentState. При отладке он показывает в методе Initialize эту строчку:
Код - C# [Выбрать]
  1. ed.EnteringQuiescentState -= new EventHandler(ed_EnteringQuiescentState);

При открытии других чертежей таких сообщений нет. Что это такое?

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Re: Removing something that wasn't added?
« Ответ #1 : 19-04-2019, 13:30:41 »
С событиями редактора надо быть аккуратным. Он не прощает отписки от события, на который не было ранее подписки и вот таким образом ругается.

Оффлайн Алексей ТерноАвтор темы

  • ADN Club
  • ****
  • Сообщений: 381
  • Карма: 33
    • C3D Extensions
  • Skype: alexeyterno
Re: Removing something that wasn't added?
« Ответ #2 : 19-04-2019, 13:35:41 »
Тогда эта ошибка должна вылезать везде, а она появляется в некоторых чертежах.

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Removing something that wasn't added?
« Ответ #3 : 19-04-2019, 13:40:47 »
Тогда эта ошибка должна вылезать везде, а она появляется в некоторых чертежах.
Нужно смотреть логику, которая у тебя прописана в Initialize. Возможно этот код не всегда вызывается. Но в любом случае Дмитрий Загорулькин абсолютно прав. Как минимум этот код следует обернуть в try/catch.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Алексей ТерноАвтор темы

  • ADN Club
  • ****
  • Сообщений: 381
  • Карма: 33
    • C3D Extensions
  • Skype: alexeyterno
Re: Removing something that wasn't added?
« Ответ #4 : 19-04-2019, 13:47:40 »
Нужно смотреть логику, которая у тебя прописана в Initialize. Возможно этот код не всегда вызывается.
Логика проста - я подписываюсь на события, которые мне необходимы, а потом добавление переопределений. Эта строчка должна вызываться всегда.
И да, Дима прав - я убрал из Initialize отписку от этого события и эта проблема ушла.
Я оставил пару отписка-подписка в событиях DocumentCreated и DocumentActivated. По идее в них такой проблемы не должно быть.

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Re: Removing something that wasn't added?
« Ответ #5 : 19-04-2019, 15:07:26 »
Я оставил пару отписка-подписка в событиях DocumentCreated и DocumentActivated. По идее в них такой проблемы не должно быть.
Плохая идея.

Оффлайн Алексей ТерноАвтор темы

  • ADN Club
  • ****
  • Сообщений: 381
  • Карма: 33
    • C3D Extensions
  • Skype: alexeyterno
Re: Removing something that wasn't added?
« Ответ #6 : 19-04-2019, 15:10:03 »
Плохая идея.
Ты предлагаешь и там убрать отписку?

Оффлайн Вильдар

  • ADN Club
  • ****
  • Сообщений: 405
  • Карма: 77
  • Skype: vildar82
Re: Removing something that wasn't added?
« Ответ #7 : 19-04-2019, 15:15:11 »
Плохая идея.
А почему?
Через трай-катч, тоже так делаю.

Отмечено как Решение Алексей Терно 20-04-2019, 12:44:10

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Re: Removing something that wasn't added?
« Ответ #8 : 19-04-2019, 15:21:57 »
Плохая идея использовать пару отписка-подписка с событиями редактора. Думаю, в данном случае надёжнее будет если сохранять состояние подписки в переменной. Подписались - значение в true. Отписались - значение в false. Собираемся подписываться или отписываться - проверяем переменную состояния.

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Re: Removing something that wasn't added?
« Ответ #9 : 19-04-2019, 15:27:21 »
Через трай-катч, тоже так делаю.
Лучше бы вообще не доводить до состояния, когда возникает исключение. Иногда такие исключения вроде как отлавливаются, но после этого что-то внутри автокада нарушается...

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Removing something that wasn't added?
« Ответ #10 : 19-04-2019, 17:56:21 »
Плохая идея.
Ты предлагаешь и там убрать отписку?
Отписываться можно только если подписался. Иначе в лучшем случае исключение, в худшем Fatal Error (зависит от типа события).
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Алексей ТерноАвтор темы

  • ADN Club
  • ****
  • Сообщений: 381
  • Карма: 33
    • C3D Extensions
  • Skype: alexeyterno
Re: Removing something that wasn't added?
« Ответ #11 : 20-04-2019, 12:43:18 »
Не отлавливается отписка от события EnteringQuiescentState трайкэтчем - все равно выскакивает это исключение. Теперь уже предложение Димы сохранять состояние подписки не кажется мне излишним )) Я думаю создать глобальный список пар [Document.Database.BlockTableId]-[состояние подписки] и пополнять его при создании или открытии чертежа.

Оффлайн Алексей ТерноАвтор темы

  • ADN Club
  • ****
  • Сообщений: 381
  • Карма: 33
    • C3D Extensions
  • Skype: alexeyterno
Re: Removing something that wasn't added?
« Ответ #12 : 20-04-2019, 13:43:35 »
Вот так вот я сделал:
Код - C# [Выбрать]
  1. public class ImplementClass0 : IExtensionApplication
  2. {
  3.     //тут я храню id всех открытых в текущий момент чертежей
  4.     //это коллекция отслеживания
  5.     private List<ObjectId> btids = new List<ObjectId>();
  6.  
  7.     public void Initialize()
  8.     {
  9.         if (Application.DocumentManager.MdiActiveDocument == null)
  10.             return;
  11.  
  12.         Document doc = Application.DocumentManager.MdiActiveDocument;
  13.         Database db = doc.Database;
  14.         Editor ed = doc.Editor;
  15.  
  16.         Application.DocumentManager.DocumentCreated += new DocumentCollectionEventHandler(doc_DocumentCreated);
  17.         Application.DocumentManager.DocumentActivated += new DocumentCollectionEventHandler(doc_DocumentActivated);
  18.         Application.DocumentManager.DocumentToBeDestroyed += new DocumentCollectionEventHandler(doc_DocumentDestroyed);
  19.  
  20.         //сразу подписываюсь на события активного чертежа и добавляю его в коллекцию отслеживания
  21.         btids.Add(db.BlockTableId);
  22.         addreactors(doc, db, ed);
  23.     }
  24.  
  25.     public void Terminate()
  26.     {
  27.         throw new NotImplementedException();
  28.     }
  29.  
  30.     public void addreactors(Document _doc, Database _db, Editor _ed)
  31.     {
  32.         _doc.Database.SystemVariableChanged += new Autodesk.AutoCAD.DatabaseServices.SystemVariableChangedEventHandler(db_SystemVariableChanged);
  33.         _doc.ImpliedSelectionChanged += new EventHandler(doc_SelectionChanged);
  34.         _doc.CommandWillStart += new CommandEventHandler(doc_MonitorCommandWillStarted);
  35.         _doc.CommandEnded += new CommandEventHandler(doc_MonitorCommandEnded);
  36.         _db.ObjectAppended += new ObjectEventHandler(db_MonitorObjectAppended);
  37.         _ed.EnteringQuiescentState += new EventHandler(ed_EnteringQuiescentState);
  38.     }
  39.  
  40.     public void doc_DocumentCreated(object sender, DocumentCollectionEventArgs e)
  41.     {
  42.         if (e.Document == null || e.Document.Database == null)
  43.             return;
  44.  
  45.         Document doc = Application.DocumentManager.MdiActiveDocument;
  46.         Database db = doc.Database;
  47.         Editor ed = doc.Editor;
  48.  
  49.         //если докемнт только что создан, значит подписки на события еще не было - подписываюсь
  50.         btids.Add(db.BlockTableId);
  51.         addreactors(doc, db, ed);
  52.     }
  53.  
  54.     public void doc_DocumentActivated(object sender, DocumentCollectionEventArgs e)
  55.     {
  56.         if (e.Document == null || e.Document.Database == null)
  57.             return;
  58.  
  59.         Document doc = Application.DocumentManager.MdiActiveDocument;
  60.         Database db = doc.Database;
  61.         Editor ed = doc.Editor;
  62.  
  63.         //если id чертежа есть в коллекции отслеживания, то подписка уже была, в противном случае - подписываюсь
  64.         if (!btids.Contains(db.BlockTableId))
  65.         {
  66.             btids.Add(db.BlockTableId);
  67.             addreactors(doc, db, ed);
  68.         }
  69.     }
  70.  
  71.     public void doc_DocumentDestroyed(object sender, DocumentCollectionEventArgs e)
  72.     {
  73.         //при закрытии чертежа удаляю его id из коллекции отслеживания
  74.         if (btids.Contains(e.Document.Database.BlockTableId))
  75.             btids.Remove(e.Document.Database.BlockTableId);
  76.     }
  77. }

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Re: Removing something that wasn't added?
« Ответ #13 : 20-04-2019, 14:33:07 »
Интересно, сработает или нет? Попробуй открыть новый чертёж командой Open, но когда откроется диалог выбора чертежа - нажми "Отмена". Должен случиться эксепшн. Отбой, увидел проверку :)
И ещё посмотри в 27 строку своего кода.

Оффлайн Алексей ТерноАвтор темы

  • ADN Club
  • ****
  • Сообщений: 381
  • Карма: 33
    • C3D Extensions
  • Skype: alexeyterno
Re: Removing something that wasn't added?
« Ответ #14 : 20-04-2019, 14:40:39 »
посмотри в 27 строку своего кода
А, да - это стандартная строчка осталась от примера ))