0

As I discovered in a previous question:

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

it appears sending commands such c:wd_insym2 (ACad Electrical command) cannot be called synchronously as it calls additional commands such as Undo, causing it to fail.

However, I need to store the EntityID of the entity I have just created with the command, using either the Lisp (entlast) or Autodesk.AutoCad.Internal.Utils.EntLast(). Obviously if I send my command asynchronously this will not give me the correct result.

Maxence suggested using the doc.CommandEnded handler, however I cannot imagine how this will fit in my program flow, as I need to execute each command individually and then store the new EntityID in a .NET variable.

Is there ANY way for me to either send such commands synchronously without running into reentrancy issues, or alternatively send commands asynchronously and wait for them to execute before continuing?

Community
  • 1
  • 1
Bill Peet
  • 477
  • 1
  • 8
  • 23

1 Answers1

1

Have you tried Editor.CommandAsync (AutoCAD 2015 and +):

[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();
  }
}

If you want to do this in an older version of AutoCAD, it will be more complicated:

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();
  }
}
Maxence
  • 12,868
  • 5
  • 57
  • 69