AutoCad NET 通过异步命令使用 EntLast

AutoCad NET use EntLast with asynchronous command

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

似乎无法同步调用 c:wd_insym2(ACad Electrical 命令)等命令,因为它会调用撤消等其他命令,导致失败。

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

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

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

您尝试过吗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();
  }
}