jtoverka 发表于 2021-4-21 08:03:39

运行AutoCAD Core控制台

先生们,
我找到了一种方法,可以在窗口不可见的情况下运行AutoCAD Core控制台,将secureload设置为0,然后Netload一个dll,运行一个带有参数、GUID字符串的.NET Lisp应用程序。此字符串是进程间通信的管道名称。这允许外部应用程序优雅地处理DWG
与AutoCAD相比,AutoCAD Core控制台本身使用的RAM非常少。当它空闲时,它使用0%的CPU功率。我遇到的问题是,我的应用程序占用了大量CPU资源。我的英特尔I9 CPU有10个内核,20个线程。它100%使用一个线程,占整个CPU的5%。当程序处于空闲状态时,我想将其减少到~0.1%
以下是我在AutoCAD Core控制台中运行的代码
using AcConsole;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using Clifton.Core.Pipes;
using NetDBX;
using System.Collections.Generic;
using System.IO;
namespace AcConsoleIn
{
    ///
    /// Provides static methods to run within AutoCAD Core Console
    ///
    public static class Run
    {
      // IPC Pipe
      private static ClientPipe Client { get; set; }
      ///
      /// Provides the Lisp Function to connect this process to an external application.
      ///
      ///
      
      public static void Process(ResultBuffer buffer)
      {
            try
            {
                using (buffer)
                {
                  // Process input
                  List args = AutoLisp.HandleLispArguments(buffer, 1, 1);
                  // Create and connect IPC pipe
                  string pipeName = AutoLisp.LispToString(args);
                  Client = new ClientPipe(".", pipeName, p => p.StartStringReaderAsync());
                  Client.DataReceived += Client_DataReceived;
                  Client.Connect();
                }
            }
            catch { }
      }
      ///
      /// Event Handler for processing data from server.
      ///
      ///
      ///
      private static void Client_DataReceived(object sender, PipeEventArgs e)
      {
            // Exit if communication pipe is broken
            if (Client == null)
                return;
            try
            {
                // Check for a close application message
                if (e.String == "Close Application")
                {
                  // Disconnect Pipe
                  Client.DataReceived -= Client_DataReceived;
                  Client.Close();
                  Client = null;
                  // Close AutoCAD
                  Autodesk.AutoCAD.ApplicationServices.Core.Application.Quit();
                  return;
                }
                // Tell server that this is busy
                Client.WriteString("1");
                // Get database object
                AcConsole.DatabaseServices.Database database;
                database = IO.XmlDeserializeFromString(e.String);
                // Throw error if it received an invalid database object
                if (database == null)
                  throw new InvalidDataException("Invalid Database Object");
                // Create new drawing
                using Database drawing = new Database(true, true);
                using (Transaction transaction = drawing.TransactionManager.StartTransaction())
                {
                  // Convert AcConsole.DatabaseServices.Database to Autodesk.AutoCAD.DatabaseServices.Database
                  database.ToDatabase(drawing, transaction);
                  transaction.Commit();
                }
                // Delete file if it exists
                string filename = database.Filename;
                if (File.Exists(filename))
                  File.Delete(filename);
                // Save drawing
                drawing.SaveAs(filename, DwgVersion.Current);
                // Tell Server it is not busy.
                Client.WriteString("0");
            }
            catch (System.Exception ex)
            {
                // Tell server that an error occured.
                Client.WriteString(ex.Message);
            }
      }
    }
}

我想如果我使用事件处理程序,当它空闲时,我不会使用任何CPU电源。有人能帮我吗?
**** Hidden Message *****

JohnK 发表于 2021-4-21 11:01:42

警告:我不擅长C#。这种反应更多的是理论方面的。
使用任务呢?
https://docs . Microsoft . com/en-us/dot net/API/system . threading . tasks . task?redirected from = MSDN & view = net-5.0

jtoverka 发表于 2021-4-21 13:33:05

谢谢John的建议,
经过更多的检查,它似乎与重定向控制台Standard IO

      ///
      /// Initializes a new instance of this class
      ///
      public Console()
      {
            try
            {
                string installpath = null;
                // Search the directory for the AutoCAD Console Application
                foreach (string file in Directory.GetFiles(@"C:\Program Files\Autodesk\", "accoreconsole.exe", SearchOption.AllDirectories))
                {
                  if (Path.GetFileName(file).Equals("accoreconsole.exe", StringComparison.OrdinalIgnoreCase))
                  {
                        installpath = file;
                        break;
                  }
                }
                // Set up process
                coreprocess.StartInfo.Arguments = "/isolate";
                coreprocess.StartInfo.UseShellExecute = false;
                coreprocess.StartInfo.CreateNoWindow = true;
                coreprocess.StartInfo.RedirectStandardOutput = false;
                coreprocess.StartInfo.RedirectStandardInput = true;
                coreprocess.StartInfo.FileName = installpath;
               
                // Start Process
                this.ConsoleStarted = coreprocess.Start();
                // Load program to AutoCAD Core Console
                if (this.ConsoleStarted)
                {
                  // Get program running inside accoreconsole
                  string loadDLL = Directory.GetCurrentDirectory() + "\\AcConsoleIn.dll";
                  using StreamWriter writer = coreprocess.StandardInput;
                  // Set up the IPC pipe connection
                  string guid = Guid.NewGuid().ToString().ToUpper();
                  server = new(guid, p => p.StartStringReaderAsync());
                  server.Connected += Server_Connected;
                  server.DataReceived += Server_DataReceived;
                  // Write to AutoCAD Core Console
                  writer.WriteLine("SECURELOAD 0");
                  writer.WriteLine("NETLOAD " + loadDLL);
                  writer.WriteLine("(PROCESS \"" + guid + "\") ");
                  writer.Close();
                }
            }
            catch { }
      }

有关
,如果我注释掉了代码的编写器部分,尽管没有运行任何东西,它仍然以5%的速度运行。但是,如果我更改以下内容:
coreprocess.StartInfo.RedirectStandardInput = false;

它以0%的速度运行。
因此,标准输入的重定向就是这样做的。如何解决此问题?
我需要写入控制台,并且不想运行100%的线程。

JohnK 发表于 2021-4-21 13:55:42

改为从文件中读取文本?我假设“ReDirectStandard ardInput”是键盘输入。

jtoverka 发表于 2021-4-21 16:15:30

我找到了。这是这一行:
writer.Close();
显然,当我删除那一行时,它解决了问题。

abcd 发表于 2021-12-7 06:49:05


你介意分享更多关于这个的信息吗?我会对你的解决方案非常感兴趣
页: [1]
查看完整版本: 运行AutoCAD Core控制台