Сообщество программистов Autodesk в СНГ

ADN Club => AutoCAD .NET API => Тема начата: Atomohod от 03-03-2021, 19:08:16

Название: eHadMultipleReaders. Причина?
Отправлено: Atomohod от 03-03-2021, 19:08:16
Здравствуйте!

Есть плагин который формирует один чертеж из нескольких составляющих. Вызывается в чистом новом открытом файле чертежа через командную строку, далее выбираем несколько интересующих нас dwg файлов на диске и жмем ОК. Плагин читает в памяти базы данных чертежей и копирует в текущий чертеж часть их содержимого, основываясь на заложенный в алгоритм фильтр выбора объектов.
При работе столкнулся с ошибкой eHadMultipleReaders. Затем выдает фатал и акад вылетает. Кто-нибудь знает как это исправить?
Autocad 2015.
(https://i.postimg.cc/rz1S3gtD/image.jpg) (https://postimg.cc/rz1S3gtD)

(https://i.postimg.cc/SnsCXh19/2.jpg) (https://postimg.cc/SnsCXh19)
Название: Re: eHadMultipleReaders. Причина?
Отправлено: Александр Ривилис от 03-03-2021, 19:11:32
Кто-нибудь знает как это исправить?
Да. Исправить программу.
Название: Re: eHadMultipleReaders. Причина?
Отправлено: Atomohod от 03-03-2021, 19:30:09
Из-за чего возникает эта ошибка?
Название: Re: eHadMultipleReaders. Причина?
Отправлено: Александр Ривилис от 03-03-2021, 19:33:31
Из-за чего возникает эта ошибка?
Причин может быть множество. Нет смысла гадать на кофейной гуще.
Название: Re: eHadMultipleReaders. Причина?
Отправлено: Atomohod от 03-03-2021, 21:08:36
Что может помочь? Код плагина слишком объемный, чтобы выкладывать полностью. Если предположить какое действие может вызывать подобную ошибку, то я смогу вытащить предполагаемый кусок кода. Где наиболее вероятна ошибка?
Название: Re: eHadMultipleReaders. Причина?
Отправлено: Александр Ривилис от 03-03-2021, 21:14:20
Что может помочь? Код плагина слишком объемный, чтобы выкладывать полностью. Если предположить какое действие может вызывать подобную ошибку, то я смогу вытащить предполагаемый кусок кода. Где наиболее вероятна ошибка?
Еще раз. Причин может быть огромное количество. Это и отсутствие Transaction.Commit() и отсутствие блокировки документа и т.д. и т.п.
Могу лишь посоветовать выбросить из плагина всю логику фильтрования и просто всё из выбранных чертежей копировать в текущий. Если ошибки не будет, то проблема в логике фильтрования. Если ошибка будет, то тогда код будет небольшой и его можно будет анализировать. Кстати, а какой метод ты используешь для копирования из чертежа в чертеж?
Название: Re: eHadMultipleReaders. Причина?
Отправлено: Atomohod от 03-03-2021, 21:22:20
Вот этот
Код - C# [Выбрать]
  1. public static void SynchronizeDrawings()
  2.         {
  3.             List < string > fileNames = Drawing.SelectDrawings();
  4.             if ( fileNames.Count == 0 )
  5.             {
  6.                 return;
  7.             }
  8.  
  9.             Document acDoc = Application.DocumentManager.MdiActiveDocument;
  10.             Database acCurDb = acDoc.Database;
  11.             ObjectId idMSpace = ObjectId.Null;
  12.             using ( Transaction acTrans = acCurDb.TransactionManager.StartTransaction() )
  13.             {
  14.                 BlockTable acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead) as BlockTable;
  15.                 idMSpace = acBlkTbl[ BlockTableRecord.ModelSpace ];
  16.                 acTrans.Commit();
  17.             }
  18.  
  19.             foreach ( string fileName in fileNames )
  20.             {
  21.                 using ( Database db = new Database(false, true) )
  22.                 {
  23.                     db.ReadDwgFile(fileName, FileOpenMode.OpenForReadAndAllShare, false, null);
  24.                     // string areaNumber = db.GetBuildingAreaNumber();
  25.  
  26.                     string areaNumber = null;
  27.                     try
  28.                     {
  29.                         areaNumber = db.GetBuildingAreaNumber();
  30.                     }
  31.                     catch ( NullReferenceException )
  32.                     {
  33.                        // Application.ShowAlertDialog("Set construction area number in source drawing by Drawing properties => subject");
  34.                     }
  35.  
  36.                     DeletePreviousEntities(areaNumber, acCurDb);
  37.  
  38.                     using ( IdMapping idMap = new IdMapping() )
  39.                     {
  40.                         db.WblockCloneObjects(Drawing.GetObjects(db), idMSpace, idMap, DuplicateRecordCloning.Ignore, false); // !!!!
  41.                     }
  42.  
  43.                     EntityProcessor.SetDynamicBlockProperty(acCurDb);
  44.  
  45.                     Logger logger = new Logger();
  46.                     logger.CreateSynchronizationLog(fileName);
  47.                 }
  48.             }
  49.         }
Название: Re: eHadMultipleReaders. Причина?
Отправлено: Александр Ривилис от 03-03-2021, 21:37:38
В это коде половина неизвестных функций. Выкинь их и просто оставь копирование. Посмотри результат. Если ошибки не будет - значит ошибка в этих функциях.
Название: Re: eHadMultipleReaders. Причина?
Отправлено: Atomohod от 03-03-2021, 22:39:18
Ошибка непостоянная - запускаю один раз работает, второй тоже, далее дохожу до какого-то 7,11,8 раза, всегда по-разному, и хватаю ошибку. Файлы указываю плагину поштучно, (хотя предусмотрена последовательная обработка из списка) это от ошибки не спасает.
Название: Re: eHadMultipleReaders. Причина?
Отправлено: Александр Ривилис от 03-03-2021, 22:50:22
Atomohod,
Это никак не поможет найти ошибку. Впрочем это может и быть и баг в AutoCAD или в одном из приложений, загруженных в AutoCAD.
Название: Re: eHadMultipleReaders. Причина?
Отправлено: Александр Ривилис от 03-03-2021, 23:04:21
Эта ошибка возникает, если забыли закрыть открытый объект/примитив. Часто это происходит в методе UpgradeOpen. Посмотри свой метод Drawing.GetObjects(db). Не оставляет ли он откытые объекты?
Название: Re: eHadMultipleReaders. Причина?
Отправлено: Atomohod от 04-03-2021, 08:19:27
Вроде бы не оставляет. Я открываю только на чтение и делаю коммит транзакции в завершение.
Код - C# [Выбрать]
  1.  public static ObjectIdCollection GetObjects(Database db)
  2.         {
  3.             ObjectIdCollection filteredEntities = new ObjectIdCollection();
  4.             List < Entity > entities = new List < Entity >();
  5.             try
  6.             {
  7.                 Transaction tr = db.TransactionManager.StartTransaction();
  8.                 using ( tr )
  9.                 {
  10.                     BlockTable bt = (BlockTable) tr.GetObject(db.BlockTableId, OpenMode.ForRead, false, false);
  11.                     BlockTableRecord btr = (BlockTableRecord) tr.GetObject(bt[ BlockTableRecord.ModelSpace ], OpenMode.ForRead);
  12.  
  13.                     foreach ( ObjectId item in btr )
  14.                     {
  15.                         Entity ent = (Entity) tr.GetObject(item, OpenMode.ForRead);
  16.  
  17.                         entities.Add(ent);
  18.                     }
  19.  
  20.                     tr.Commit();
  21.                 }
  22.  
  23.                 var boundaries = Selector.GetBoundariesObjectId(db);
  24.  
  25.                 var entitiesOnLayers = Selector.SelectEntityOnDesiredLayers(entities);
  26.                 foreach ( var ent in entitiesOnLayers )
  27.                 {
  28.                     if ( Selector.IsEntityValidForSync(ent, boundaries) )
  29.                     {
  30.                         filteredEntities.Add(ent.ObjectId);
  31.                     }
  32.                 }
  33.             }
  34.             catch ( Exception ex )
  35.             {
  36.                 Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage(ex.ToString());
  37.             }
  38.  
  39.             Marker.AttachXDataToSelectionSetObjects(ref filteredEntities, db);
  40.  
  41.             return filteredEntities;
  42.         }
Название: Re: eHadMultipleReaders. Причина?
Отправлено: Дмитрий Загорулькин от 04-03-2021, 09:46:52
Вроде бы не оставляет. Я открываю только на чтение и делаю коммит транзакции в завершение.
См. строки 4, 15, 20 и 25, 28, 30.
Название: Re: eHadMultipleReaders. Причина?
Отправлено: Александр Ривилис от 04-03-2021, 10:36:04
Atomohod,
Ты делаешь еще хуже - пользуешься объектами, открытыми в транзакции после завершения транзакции.
Название: Re: eHadMultipleReaders. Причина?
Отправлено: Atomohod от 04-03-2021, 15:04:15
То есть я не могу в одной транзакции получить нужные мне объекты, а обработать в другой? Вроде бы вложенные транзакции не запрещены. Почему тогда они не пригодны для обработки в рамках одной сессии? Я не понял.
Название: Re: eHadMultipleReaders. Причина?
Отправлено: Привалов Дмитрий от 04-03-2021, 15:17:12
То есть я не могу в одной транзакции получить нужные мне объекты, а обработать в другой?
когда вызвал tr.Commit(); ты закрыл объекты.
Передавать между транзакциями нужно ObjectId. И вновь открывать объекты.
Название: Re: eHadMultipleReaders. Причина?
Отправлено: Александр Ривилис от 04-03-2021, 15:20:34
То есть я не могу в одной транзакции получить нужные мне объекты, а обработать в другой?
Нет.
Вроде бы вложенные транзакции не запрещены.
Здесь в коде нет вложенных транзакций. Здесь независимые транзакции.
Еще раз. За пределами транзакции нельзя использовать открытые в транзакции объекты.
Название: Re: eHadMultipleReaders. Причина?
Отправлено: Александр Ривилис от 04-03-2021, 15:45:17
когда вызвал tr.Commit(); ты закрыл объекты.
Если быть точным, то не только tr.Commit() закрывает объекты. Если не было бы tr.Commit(), то по деструктору tr (закрывающаяся скобка у using) было бы тоже закрытие объектов, только с откатом (аналог DBObject.Abort() вместо DBObject.Close()).
Название: Re: eHadMultipleReaders. Причина?
Отправлено: Atomohod от 04-03-2021, 20:07:10
Передавать между транзакциями нужно ObjectId. И вновь открывать объекты.
Так я же и возвращаю из метода коллекцию ObjectId - public static ObjectIdCollection GetObjects(Database db). Как еще их передать? Через List<ObjectId>?
Название: Re: eHadMultipleReaders. Причина?
Отправлено: Александр Ривилис от 04-03-2021, 20:13:23
Atomohod,
При вызове Selector.SelectEntityOnDesiredLayers ты передаешь коллекцию Entity, которые уже не валидные, так как транзакция, в которой они открыты, уже завершена. Что непонятно?
Название: Re: eHadMultipleReaders. Причина?
Отправлено: Александр Ривилис от 04-03-2021, 20:16:23
Atomohod,
И не увлекайся var - в твоём коде не поймёшь где ObjectId, а где Entity. Тем более, что имена переменных как будто специально сбивают с толку.