简体   繁体   English

AutoCad NET将EntLast与异步命令一起使用

[英]AutoCad NET use EntLast with asynchronous command

As I discovered in a previous question: 正如我在上一个问题中发现的那样:

AutoCad Command Rejected "Undo" when using Application.Invoke() 使用Application.Invoke()时,AutoCad命令被拒绝为“撤消”

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. 似乎发送命令c:wd_insym2(ACad Electrical命令)不能被同步调用,因为它会调用其他命令(例如撤消),从而导致失败。

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(). 但是,我需要使用Lisp(entlast)或Autodesk.AutoCad.Internal.Utils.EntLast()存储刚刚通过命令创建的实体的EntityID。 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. Maxence建议使用doc.CommandEnded处理程序,但是我无法想象这将如何适合我的程序流程,因为我需要分别执行每个命令,然后将新的EntityID存储在.NET变量中。

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

Have you tried Editor.CommandAsync (AutoCAD 2015 and +): 您是否尝试过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();
  }
}

If you want to do this in an older version of AutoCAD, it will be more complicated: 如果要在较旧版本的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();
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM