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

ADN Club => AutoCAD .NET API => Тема начата: Atomohod от 14-10-2019, 23:08:56

Название: Не изменяется видимость динамического блока
Отправлено: Atomohod от 14-10-2019, 23:08:56
Здравствуйте!

Словил ошибку при попытке смены видимости динамического блока.
System.InvalidOperationException
  HResult=0x80131509
  Сообщение = Operation is not valid due to the current state of the object.
  Источник = Acdbmgd
  Трассировка стека:
   at Autodesk.AutoCAD.DatabaseServices.Transaction.CheckTopTransaction()
   at Autodesk.AutoCAD.DatabaseServices.Transaction.DeleteUnmanagedObject()
   at Autodesk.AutoCAD.Runtime.DisposableWrapper.!DisposableWrapper()
   at Autodesk.AutoCAD.Runtime.DisposableWrapper.Dispose(Boolean A_0)
   at Autodesk.AutoCAD.Runtime.DisposableWrapper.Dispose()
   at DrawingSynchronizer.EntityProcessor.SetDynamicBlkProperty2() in K:\DevProjects\AutoCAD\DrawingSynchronizer\EntityProcessor.cs:line 153
   at Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorker(MethodInfo mi, Object commandObject, Boolean bLispFunction)
   at Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorkerWithExceptionFilter(MethodInfo mi, Object commandObject, Boolean bLispFunction)
   at Autodesk.AutoCAD.Runtime.CommandClass.CommandThunk.Invoke()

Как это исправить?

Код - C# [Выбрать]
  1.         [CommandMethod("SetDynamicBlkProperty2")]
  2.         public static void SetDynamicBlkProperty2()
  3.  
  4.         {
  5.             Document doc = Application.DocumentManager.MdiActiveDocument;
  6.             Database db = doc.Database;
  7.  
  8.             using (Transaction tr = db.TransactionManager.StartTransaction())
  9.  
  10.             {
  11.                 BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead, false, true);
  12.                 BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead, false, true);
  13.                 foreach (ObjectId entity in btr)
  14.                 {
  15.                     Entity ent = (Entity)tr.GetObject(entity, OpenMode.ForRead);
  16.                     if (ent is BlockReference)
  17.                     {
  18.                         BlockReference bref = tr.GetObject(entity, OpenMode.ForWrite, false, true) as BlockReference;
  19.  
  20.                         if (bref.IsDynamicBlock)
  21.  
  22.                         {
  23.                             BlockTableRecord dynBtr = (BlockTableRecord)tr.GetObject(bref.DynamicBlockTableRecord, OpenMode.ForWrite, false, true);
  24.                             var blockNames = GetBlockNames("C:\\Developments\\Lists\\ListOfBlocks.txt");
  25.                             if (blockNames.Contains(dynBtr.Name) )
  26.                             {
  27.                                 DynamicBlockReferencePropertyCollection props = bref.DynamicBlockReferencePropertyCollection;
  28.  
  29.                                 foreach (DynamicBlockReferenceProperty prop in props)
  30.  
  31.                                 {
  32.                                     object[] values = prop.GetAllowedValues();
  33.  
  34.                                     //Switch Property
  35.  
  36.                                     if ((prop.PropertyName == "Visibility") && !prop.ReadOnly)
  37.  
  38.                                     {
  39.                                         if (prop.Value.ToString() == values[0].ToString())
  40.                                         {
  41.                                             prop.Value = values[1];
  42.                                         }
  43.  
  44.                                         else
  45.                                         {
  46.                                             prop.Value = values[0];
  47.                                         }
  48.                                     }
  49.                                 }
  50.                             }
  51.                         }
  52.                     }
  53.                 }
  54.  
  55.                 tr.Commit();
  56.             }
  57.         }
Код - C# [Выбрать]
  1.  public static List < string > GetBlockNames(string path)
  2.         {
  3.             Document doc = Application.DocumentManager.MdiActiveDocument;
  4.             Database db = doc.Database;
  5.             Transaction tr = doc.TransactionManager.StartTransaction();
  6.  
  7.             List < string > listOfBlockNames = new List < string >();
  8.             string filePath = path;
  9.  
  10.             StreamReader sr = new StreamReader(filePath, Encoding.Default);
  11.  
  12.             string line;
  13.             while ( (line = sr.ReadLine()) != null )
  14.             {
  15.                 listOfBlockNames.Add(line);
  16.             }
  17.            
  18.             return listOfBlockNames;
  19.         }
Название: Re: Не изменяется видимость динамического блока
Отправлено: Александр Ривилис от 14-10-2019, 23:18:29
Что в строке K:\DevProjects\AutoCAD\DrawingSynchronizer\EntityProcessor.cs:line 153 на которой возникает ошибка?
Название: Re: Не изменяется видимость динамического блока
Отправлено: Atomohod от 14-10-2019, 23:52:50
Что в строке K:\DevProjects\AutoCAD\DrawingSynchronizer\EntityProcessor.cs:line 153 на которой возникает ошибка?
В этом и прикол - ничего, там скобка.
(https://i.postimg.cc/fk0mrDFQ/2019-10-14-235129.jpg) (https://postimg.cc/fk0mrDFQ)
Название: Re: Не изменяется видимость динамического блока
Отправлено: Александр Ривилис от 14-10-2019, 23:57:41
В этом и прикол - ничего, там скобка.
В этот момент выполняется tr.Dispose() и tr уже почему-то разрушен. tr.Commit() у тебя случайно не внутри цикла foreach?
Кроме того поменяй
Код - C# [Выбрать]
  1. BlockTableRecord dynBtr = (BlockTableRecord)tr.GetObject(bref.DynamicBlockTableRecord, OpenMode.ForWrite, false, true);
на
Код - C# [Выбрать]
  1. BlockTableRecord dynBtr = (BlockTableRecord)tr.GetObject(bref.DynamicBlockTableRecord, OpenMode.ForRead);
Название: Re: Не изменяется видимость динамического блока
Отправлено: Александр Ривилис от 15-10-2019, 00:25:05
Atomohod,
Нашел в чем у тебя ошибка - тупой копипапаст кода:
Код - C# [Выбрать]
  1.      public static List < string > GetBlockNames(string path)
  2.             {
  3. //                Document doc = Application.DocumentManager.MdiActiveDocument; // <--- Убрать - не нужно
  4. //                Database db = doc.Database; // <--- Убрать не нужно
  5. //                Transaction tr = doc.TransactionManager.StartTransaction(); // <--- Убрать - не нужно и чревато, так как создаётся транзакция, но нигде не завершается (нет tr.Dispose())
  6.      
  7.                 List < string > listOfBlockNames = new List < string >();
  8.                 string filePath = path;
  9.      
  10.                 StreamReader sr = new StreamReader(filePath, Encoding.Default);
  11.      
  12.                 string line;
  13.                 while ( (line = sr.ReadLine()) != null )
  14.                 {
  15.                     listOfBlockNames.Add(line);
  16.                 }
  17.                
  18.                 return listOfBlockNames;
  19.             }
Название: Re: Не изменяется видимость динамического блока
Отправлено: Привалов Дмитрий от 15-10-2019, 08:38:14
Словил ошибку при попытке смены видимости динамического блока.
Почитай что такое рефакторинг кода. Это нормально, что в коде сделанном наспех содержатся ошибки и не оптимальное использование ресурсов. Последующий рефакторинг поможет тебе заметишь ошибки.

может быть ошибка в логике переключения видимости
object[] values = prop.GetAllowedValues(); ты не проверяешь сколько значений вернул метод,
Если одно или ноль, тогда prop.Value = values[1] и prop.Value = values[0] вызовет ошибку.

Еще по мелочи
//string filePath = path; строчка лишняя.
StreamReader sr = new StreamReader(path, Encoding.Default);

var blockNames = GetBlockNames("C:\\Developments\\Lists\\ListOfBlocks.txt");
...внутри цикла foreach? ...хм.
Название: Re: Не изменяется видимость динамического блока
Отправлено: Дмитрий Загорулькин от 15-10-2019, 10:29:29
В этом и прикол - ничего, там скобка.
Это не просто скобка. Это место завершения блока using и в нём происходит вызов метода Dispose для объекта, заключённого в этот блок. Что, собственно, и видно в стеке выше:
at Autodesk.AutoCAD.Runtime.DisposableWrapper.Dispose()
Название: Re: Не изменяется видимость динамического блока
Отправлено: Atomohod от 15-10-2019, 19:33:27
Кроме того поменяй
Код - C# [Выбрать]

    BlockTableRecord dynBtr = (BlockTableRecord)tr.GetObject(bref.DynamicBlockTableRecord, OpenMode.ForWrite, false, true);

на
Код - C# [Выбрать]

    BlockTableRecord dynBtr = (BlockTableRecord)tr.GetObject(bref.DynamicBlockTableRecord, OpenMode.ForRead);

Для чего заменить на чтение я понял, но если я уберу true для чтения на закрытых слоях, а у меня там тоже блоки? Как тогда это сделать?
Название: Re: Не изменяется видимость динамического блока
Отправлено: Александр Ривилис от 15-10-2019, 19:43:20
Для чего заменить на чтение я понял, но если я уберу true для чтения на закрытых слоях, а у меня там тоже блоки? Как тогда это сделать?
Ты в любом случае в своём коде не меняешь dynBtr - значит нечего открывать его ForWrite.
Название: Re: Не изменяется видимость динамического блока
Отправлено: Дмитрий Загорулькин от 15-10-2019, 19:47:39
Для чего заменить на чтение я понял, но если я уберу true для чтения на закрытых слоях, а у меня там тоже блоки? Как тогда это сделать?
BlockTableRecord не может находиться на слое, это не Entity.
Название: Re: Не изменяется видимость динамического блока
Отправлено: Atomohod от 15-10-2019, 19:51:29
значит нечего открывать его ForWrite.
А если случайно открою не то что надо, то какие могут быть последствия? ForWrite более ресурсоемкий?
Название: Re: Не изменяется видимость динамического блока
Отправлено: Atomohod от 15-10-2019, 20:03:12
BlockTableRecord не может находиться на слое, это не Entity.
Почему тогда в методе присутствуют эти параметры, они не обрабатываются?
Название: Re: Не изменяется видимость динамического блока
Отправлено: Дмитрий Загорулькин от 15-10-2019, 20:06:49
Почему тогда в методе присутствуют эти параметры
Разработчики AutoCAD API не стали делать отдельные методы на открытие разных типов объектов. Сделали один универсальный метод.
они не обрабатываются?
Да, игнорируются.
Название: Re: Не изменяется видимость динамического блока
Отправлено: Александр Ривилис от 15-10-2019, 20:07:12
ForWrite более ресурсоемкий?
Да.
Почему тогда в методе присутствуют эти параметры, они не обрабатываются?
В каком методе и какие параметры?
Название: Re: Не изменяется видимость динамического блока
Отправлено: Atomohod от 15-10-2019, 20:13:38
В каком методе и какие параметры?
Я про GetObject. Дмитрий в ответе выше объяснил мне, параметры действительно не обрабатываются. Я разобрался, спасибо!