Не изменяется видимость динамического блока

Автор Тема: Не изменяется видимость динамического блока  (Прочитано 5067 раз)

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

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

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Здравствуйте!

Словил ошибку при попытке смены видимости динамического блока.
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.         }

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Что в строке K:\DevProjects\AutoCAD\DrawingSynchronizer\EntityProcessor.cs:line 153 на которой возникает ошибка?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Что в строке K:\DevProjects\AutoCAD\DrawingSynchronizer\EntityProcessor.cs:line 153 на которой возникает ошибка?
В этом и прикол - ничего, там скобка.


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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
В этом и прикол - ничего, там скобка.
В этот момент выполняется 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);
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Отмечено как Решение Atomohod 15-10-2019, 19:26:57

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
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.             }
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 534
  • Карма: 117
Словил ошибку при попытке смены видимости динамического блока.
Почитай что такое рефакторинг кода. Это нормально, что в коде сделанном наспех содержатся ошибки и не оптимальное использование ресурсов. Последующий рефакторинг поможет тебе заметишь ошибки.

может быть ошибка в логике переключения видимости
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? ...хм.

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
В этом и прикол - ничего, там скобка.
Это не просто скобка. Это место завершения блока using и в нём происходит вызов метода Dispose для объекта, заключённого в этот блок. Что, собственно, и видно в стеке выше:
at Autodesk.AutoCAD.Runtime.DisposableWrapper.Dispose()

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Кроме того поменяй
Код - C# [Выбрать]

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

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

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

Для чего заменить на чтение я понял, но если я уберу true для чтения на закрытых слоях, а у меня там тоже блоки? Как тогда это сделать?

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Для чего заменить на чтение я понял, но если я уберу true для чтения на закрытых слоях, а у меня там тоже блоки? Как тогда это сделать?
Ты в любом случае в своём коде не меняешь dynBtr - значит нечего открывать его ForWrite.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Для чего заменить на чтение я понял, но если я уберу true для чтения на закрытых слоях, а у меня там тоже блоки? Как тогда это сделать?
BlockTableRecord не может находиться на слое, это не Entity.

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
значит нечего открывать его ForWrite.
А если случайно открою не то что надо, то какие могут быть последствия? ForWrite более ресурсоемкий?

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
BlockTableRecord не может находиться на слое, это не Entity.
Почему тогда в методе присутствуют эти параметры, они не обрабатываются?

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Почему тогда в методе присутствуют эти параметры
Разработчики AutoCAD API не стали делать отдельные методы на открытие разных типов объектов. Сделали один универсальный метод.
они не обрабатываются?
Да, игнорируются.

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
ForWrite более ресурсоемкий?
Да.
Почему тогда в методе присутствуют эти параметры, они не обрабатываются?
В каком методе и какие параметры?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
В каком методе и какие параметры?
Я про GetObject. Дмитрий в ответе выше объяснил мне, параметры действительно не обрабатываются. Я разобрался, спасибо!