【问题标题】:AutoCad NET use EntLast with asynchronous commandAutoCad NET 使用 EntLast 和异步命令
【发布时间】:2015-09-23 23:04:37
【问题描述】:

正如我在上一个问题中发现的那样:

AutoCad Command Rejected "Undo" when using Application.Invoke()

它似乎无法同步调用诸如 c:wd_insym2(ACad 电气命令)之类的命令,因为它会调用其他命令(例如 Undo),从而导致它失败。

但是,我需要使用 Lisp (entlast) 或 Autodesk.AutoCad.Internal.Utils.EntLast() 存储刚刚使用命令创建的实体的 EntityID。显然,如果我异步发送命令,这不会给我正确的结果。

Maxence 建议使用 doc.CommandEnded 处理程序,但是我无法想象这将如何适合我的程序流程,因为我需要单独执行每个命令,然后将新的 EntityID 存储在 .NET 变量中。

我有什么方法可以同步发送此类命令而不会遇到重入问题,或者异步发送命令并等待它们执行后再继续?

【问题讨论】:

    标签: c# .net vb.net autocad


    【解决方案1】:

    您是否尝试过Editor.CommandAsync(AutoCAD 2015 和 +):

    [CommandMethod("CMD1")]
    public async void Command1()
    {
      Document doc = Application.DocumentManager.MdiActiveDocument;
      Editor ed = doc.Editor;
    
      await ed.CommandAsync("_CMD2");
    
      ed.WriteMessage("Last entity handle: {0}", Utils.EntLast().Handle);
    }
    
    [CommandMethod("CMD2")]
    public void Command2()
    {
      Document doc = Application.DocumentManager.MdiActiveDocument;
      Database db = doc.Database;
      using (Transaction tr = db.TransactionManager.StartTransaction())
      {
        var line = new Line(new Point3d(), new Point3d(10, 20, 30));
        var currentSpace = (BlockTableRecord) tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
        currentSpace.AppendEntity(line);
        tr.AddNewlyCreatedDBObject(line, true);
        tr.Commit();
      }
    }
    

    如果您想在旧版本的 AutoCAD 中执行此操作,会更加复杂:

    List<ObjectId> ids;
    
    [CommandMethod("CMD1")]
    public void Cmd1()
    {
      Document doc = Application.DocumentManager.MdiActiveDocument;
      ids = new List<ObjectId>();
      doc.CommandEnded += Doc_CommandEnded;
      doc.SendStringToExecute("_CMD2 0 ", false, false, true);
    }
    
    private void Doc_CommandEnded(object sender, CommandEventArgs e)
    {
      if (e.GlobalCommandName != "CMD2") return;
    
      ids.Add(Utils.EntLast());
    
      var doc = (Document) sender;
      if (ids.Count < 10)
      {
        double angle = ids.Count * Math.PI / 10;
        doc.SendStringToExecute("_CMD2 " + Converter.AngleToString(angle) + "\n", false, false, true);
      }
      else
      {
        doc.CommandEnded -= Doc_CommandEnded;
        doc.Editor.WriteMessage("\nHandles: {0}", string.Join(", ", ids.Select(id => id.Handle.ToString())));
      }
    }
    
    [CommandMethod("CMD2")]
    public void Cmd2()
    {
      Document doc = Application.DocumentManager.MdiActiveDocument;
      Database db = doc.Database;
      PromptDoubleResult pdr = doc.Editor.GetAngle("\nAngle: ");
      if (pdr.Status == PromptStatus.Cancel) return;
    
      using (Transaction tr = db.TransactionManager.StartTransaction())
      {
        var line = new Line(new Point3d(), new Point3d(Math.Cos(pdr.Value), Math.Sin(pdr.Value), 0));
        var currentSpace = (BlockTableRecord) tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
        currentSpace.AppendEntity(line);        
        tr.AddNewlyCreatedDBObject(line, true);
        tr.Commit();
      }
    }
    

    【讨论】:

    • 谢谢。直到现在才知道 Await 命令的存在!
    • 我正在使用 AutoCad 2013。Editor.CommandAsync() 的等价物是什么?
    • 如何使用 AutoCad 2013 实现这一点?
    • 我已经更新了 2015 年之前 AutoCAD 版本的答案
    猜你喜欢
    • 2015-06-04
    • 2013-06-25
    • 1970-01-01
    • 1970-01-01
    • 2020-10-03
    • 2010-09-14
    • 2011-01-23
    • 2015-08-24
    相关资源
    最近更新 更多