Многоразовый запуск метода через событие. Как реализовать?

Автор Тема: Многоразовый запуск метода через событие. Как реализовать?  (Прочитано 6544 раз)

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

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Здравствуйте!
Пытаюсь освоить работу с событиями. Суть моей задачи-есть код, вставляющий блок позиции в чертеж. Работает как надо, но один раз. Я хочу заставить его запускаться повторно при наступлении события добавления блока предыдущей позиции в базу данных чертежа неограниченное число раз. Подписался на событие acCurDb.ObjectAppended, но в результате получил зацикливание. В чем я неправ?
Код - C# [Выбрать]
  1. namespace MarksUtilities
  2. {
  3.  
  4.      using Autodesk.AutoCAD.ApplicationServices;
  5.      using Autodesk.AutoCAD.DatabaseServices;
  6.      using Autodesk.AutoCAD.EditorInput;
  7.      using Autodesk.AutoCAD.Geometry;
  8.      using Autodesk.AutoCAD.Runtime;
  9.  
  10.      using Application = Autodesk.AutoCAD.ApplicationServices.Core.Application;
  11.  
  12.      public class InsertPosMark
  13.      {
  14.           protected Point3d GetUserPoint( )
  15.  
  16.           {
  17.                Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
  18.                Document acCurDoc = Application.DocumentManager.MdiActiveDocument;
  19.                Database acCurDb = acCurDoc.Database;
  20.  
  21.                PromptPointOptions pickPoint = new PromptPointOptions("Specify the insertion point: ");
  22.                PromptPointResult userPointResult = ed.GetPoint(pickPoint);
  23.  
  24.                return userPointResult.Value;
  25.           }
  26.  
  27.  
  28.           [CommandMethod("InsBlockWithAnAttribute")]
  29.           public void InsertBlockWithAnAttribute( )
  30.           {
  31.                
  32.                Document acDoc = Application.DocumentManager.MdiActiveDocument;
  33.                Database acCurDb = acDoc.Database;
  34.  
  35.                Point3d insertionPoint = GetUserPoint( );
  36.  
  37.                using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction( ))
  38.                {
  39.                     // Open the Block table for read
  40.                     BlockTable acBlkTbl;
  41.                     acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead) as BlockTable;
  42.  
  43.                     ObjectId blkRecId = ObjectId.Null;
  44.  
  45.                     if (!acBlkTbl.Has("PosMark"))
  46.                     {
  47.                          using (BlockTableRecord acBlkTblRec = new BlockTableRecord( ))
  48.                          {
  49.                               acBlkTblRec.Name = "PosMark";
  50.  
  51.                               // Set the insertion point for the block
  52.                               acBlkTblRec.Origin = new Point3d(0, 0, 0);
  53.  
  54.                               // Add a circle to the block
  55.                               using (Circle acCirc = new Circle( ))
  56.                               {
  57.                                    acCirc.Center = new Point3d(0, 0, 0);
  58.                                    acCirc.Radius = 4.5;
  59.  
  60.                                    acBlkTblRec.AppendEntity(acCirc);
  61.  
  62.                                    acBlkTbl.UpgradeOpen( );
  63.                                    acBlkTbl.Add(acBlkTblRec);
  64.                                    acTrans.AddNewlyCreatedDBObject(acBlkTblRec, true);
  65.  
  66.                                    // Add an attribute definition to the block
  67.                                    using (AttributeDefinition posNumber = new AttributeDefinition( ))
  68.                                    {
  69.                                         posNumber.Position = new Point3d(0, 0, 0);
  70.                                         posNumber.Prompt = "Position Number";
  71.                                         posNumber.Tag = "PosNumber";
  72.                                         posNumber.TextString = "1";
  73.                                         posNumber.Height = acCirc.Radius * 0.7;
  74.                                         posNumber.Justify = AttachmentPoint.MiddleCenter;
  75.                                         acBlkTblRec.AppendEntity(posNumber);
  76.                                    }
  77.  
  78.                                    using (AttributeDefinition designation = new AttributeDefinition( ))
  79.                                    {
  80.                                         designation.Position = new Point3d(0, -5, 0);
  81.                                         designation.Prompt = "Designation";
  82.                                         designation.Tag = "Designation";
  83.                                         designation.TextString = "Помещение";
  84.                                         designation.Invisible = true;
  85.                                         designation.Height = 5;
  86.                                         designation.Justify = AttachmentPoint.MiddleCenter;
  87.                                         acBlkTblRec.AppendEntity(designation);
  88.                                    }
  89.  
  90.                                    using (AttributeDefinition spaceNumber = new AttributeDefinition( ))
  91.                                    {
  92.                                         spaceNumber.Position = new Point3d(0, -10, 0);
  93.                                         spaceNumber.Prompt = "Space number";
  94.                                         spaceNumber.Tag = "SpaceNumber";
  95.                                         spaceNumber.TextString = "01525";
  96.                                         spaceNumber.Invisible = true;
  97.                                         spaceNumber.Height = 5;
  98.                                         spaceNumber.Justify = AttachmentPoint.MiddleCenter;
  99.                                         acBlkTblRec.AppendEntity(spaceNumber);
  100.                                    }
  101.  
  102.                                    using (AttributeDefinition mainWatertightCompartment = new AttributeDefinition( ))
  103.                                    {
  104.                                         mainWatertightCompartment.Position = new Point3d(0, -15, 0);
  105.                                         mainWatertightCompartment.Prompt = "Main watertight compartment";
  106.                                         mainWatertightCompartment.Tag = "MWC";
  107.                                         mainWatertightCompartment.TextString = "01";
  108.                                         mainWatertightCompartment.Invisible = true;
  109.                                         mainWatertightCompartment.Height = 5;
  110.                                         mainWatertightCompartment.Justify = AttachmentPoint.MiddleCenter;
  111.                                         acBlkTblRec.AppendEntity(mainWatertightCompartment);
  112.                                    }
  113.  
  114.                                    using (AttributeDefinition gastightContour = new AttributeDefinition( ))
  115.                                    {
  116.                                         gastightContour.Position = new Point3d(0, -20, 0);
  117.                                         gastightContour.Prompt = "Gastight contour";
  118.                                         gastightContour.Tag = "GastightContour";
  119.                                         gastightContour.TextString = "015";
  120.                                         gastightContour.Invisible = true;
  121.                                         gastightContour.Height = 5;
  122.                                         gastightContour.Justify = AttachmentPoint.MiddleCenter;
  123.                                         acBlkTblRec.AppendEntity(gastightContour);
  124.                                    }
  125.  
  126.                                    using (AttributeDefinition fireRatingClass = new AttributeDefinition( ))
  127.                                    {
  128.                                         fireRatingClass.SetDatabaseDefaults(acBlkTbl.Database);
  129.                                         fireRatingClass.Position = new Point3d(0, -25, 0);
  130.                                         fireRatingClass.Prompt = "Fire rating class";
  131.                                         fireRatingClass.Tag = "FireRatingClass";
  132.                                         fireRatingClass.TextString = "1";
  133.                                         fireRatingClass.Invisible = true;
  134.                                         fireRatingClass.Height = 5;
  135.                                         fireRatingClass.Justify = AttachmentPoint.MiddleCenter;
  136.                                         fireRatingClass.Position= new Point3d(0,-50,0);
  137.                                         fireRatingClass.AlignmentPoint=new Point3d(0,50,0);
  138.                                         fireRatingClass.AdjustAlignment(acBlkTbl.Database);
  139.                                         acBlkTblRec.AppendEntity(fireRatingClass);
  140.                                    }
  141.  
  142.                                    blkRecId = acBlkTblRec.Id;
  143.                               }
  144.                          }
  145.                     }
  146.                     else
  147.                     {
  148.                          blkRecId = acBlkTbl ["PosMark"];
  149.                     }
  150.  
  151.                     // Insert the block into the current space
  152.                     if (blkRecId != ObjectId.Null)
  153.                     {
  154.                          BlockTableRecord acBlkTblRec = acTrans.GetObject(blkRecId, OpenMode.ForRead) as BlockTableRecord;
  155.  
  156.                          // Create and insert the new block reference
  157.                          using (BlockReference acBlkRef = new BlockReference(insertionPoint, blkRecId))
  158.                          {
  159.                               BlockTableRecord acCurSpaceBlkTblRec = acTrans.GetObject(acCurDb.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
  160.  
  161.                               acCurSpaceBlkTblRec.AppendEntity(acBlkRef);
  162.                               acTrans.AddNewlyCreatedDBObject(acBlkRef, true);
  163.  
  164.                               // Verify block table record has attribute definitions associated with it
  165.                               if (acBlkTblRec.HasAttributeDefinitions)
  166.                               {
  167.                                    foreach (ObjectId objID in acBlkTblRec)
  168.                                    {
  169.                                         DBObject dbObj = acTrans.GetObject(objID, OpenMode.ForRead);
  170.  
  171.                                         if (dbObj is AttributeDefinition)
  172.                                         {
  173.                                              AttributeDefinition acAtt = dbObj as AttributeDefinition;
  174.  
  175.                                              if (!acAtt.Constant)
  176.                                              {
  177.                                                   using (AttributeReference acAttRef = new AttributeReference( ))
  178.                                                   {
  179.                                                        acAttRef.SetAttributeFromBlock(acAtt, acBlkRef.BlockTransform);
  180.                                                        acAttRef.Position = acAtt.Position.TransformBy(acBlkRef.BlockTransform);
  181.                                                        acAttRef.TextString = acAtt.TextString;
  182.                                                        acBlkRef.AttributeCollection.AppendAttribute(acAttRef);
  183.                                                        acTrans.AddNewlyCreatedDBObject(acAttRef, true);
  184.                                                   }
  185.                                              }
  186.                                         }
  187.                                    }
  188.                               }
  189.                          }
  190.                     }
  191.  
  192.                     acTrans.Commit( );
  193.                    
  194.                }
  195.                acCurDb.ObjectAppended += AcCurDb_ObjectAppended;
  196.           }
  197.  
  198.           private void AcCurDb_ObjectAppended(object sender, ObjectEventArgs e)
  199.           {
  200.                this.InsertBlockWithAnAttribute();
  201.           }
  202.      }
  203.  
  204. }

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Подписался на событие acCurDb.ObjectAppended, но в результате получил зацикливание.
А чего ты ожидал? Ты даже не проверяешь что добавляется в базу.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Ты даже не проверяешь что добавляется в базу.
Я думал, что мой новый blockReference. Ведь между окончанием работы моей команды и событием нет никакого иного действия. Я работаю с ним внутри транзакции к как только ее закрываю, то перехватываю событие и запускаю метод заново. Видимо что-то не то думал... Как мне исправить код?

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Я думал, что мой новый blockReference.
Думал неправильно. Запусти под отладчиком и посмотри. Кроме того в событиях (почти во всех) нельзя интерактивно обращаться к AutoCAD (т.е. то что делается в твоём методе GetUserPoint).
P.S.: Я думаю тебе следует отказаться от самой идеи это делать. Если хочешь изучать события в AutoCAD .NET API, то найди какое-то другое применение им.
В крайнем случае если твой блок вставляется только по команде InsBlockWithAnAttribute, то используй событие завершение команды InsBlockWithAnAttribute (CommandEnded). Хотя и это тоже полный бред.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
И почему вместо всех этих извращений с событиями просто не зациклить твой метод до нажатия Enter вместо указания точки. Только метод GetUserPoint придётся переделать, чтобы можно было понять указал ли пользователь точку, нажал Enter или Esc. Чего уж проще...
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Подписался на событие acCurDb.ObjectAppended, но в результате получил зацикливание. В чем я неправ?
Конечно же, будет зацикливание. Тут рекурсия в чистом виде. Добавляется объект в чертёж - запускается обработка события ObjectAppended, в котором также добавляются объекты в чертёж - при каждом добавлении объекта снова запускается обработка события ObjectAppended... И так лавинообразно до тех пор, пока не возникнет Exception переполнения памяти или ещё какой-нибудь. Более того, при обработке события ObjectAppended запускается метод, в котором ещё раз подписываемся на это событие. В .NET повторная подписка на событие означает, что обработчик будет вызываться несколько раз, при возникновении одного события. Это ещё больше усугубляет ситуацию.