NX二次开发的内部开发模式不能做多线程,只能单线程。就好比要写一个程序创建100个块,一定要在入口函数的主线程上创建100个块,如果在开几个线程去同时创建块,那么NX就会报错挂掉。
但是,NX二次开发的外部开发模式做好exe,在去写另一个多线程的程序,调用这个exe是可以的。
我认为在NX里做创建特征等相关的操作,与部件导航器等需要记录特征和对象创建的,就必须要单线程。如果同时多线程创建100个块,那部件导航器的建模顺序都乱掉了,所以不能多线程。
而做一个与上面无关的操作,还是可以的。比如:批量打印图纸,批量导出模型这些。封装成exe,应用多线程技术就可以提速很多了。
下面的例子是先用一个线程导出20张pdf,在用四个线程导出20张pdf。我们来对比下速度。
1.封装exe(NXC#项目)
NX11+VS2013 using System; using NXOpen; using NXOpen.UF; public class Program { // class members private static Session theSession; private static UFSession theUfSession; public static Program theProgram; public static bool isDisposeCalled; //------------------------------------------------------------------------------ // Constructor //------------------------------------------------------------------------------ public Program() { try { theSession = Session.GetSession(); theUfSession = UFSession.GetUFSession(); isDisposeCalled = false; } catch (NXOpen.NXException ex) { // ---- Enter your exception handling code here ----- // UI.GetUI().NXMessageBox.Show("Message", NXMessageBox.DialogType.Error, ex.Message); } } //------------------------------------------------------------------------------ // Explicit Activation // This entry point is used to activate the application explicitly //------------------------------------------------------------------------------ public static int Main(string[] args) { int retValue = 0; try { theProgram = new Program(); //TODO: Add your application code here Console.WriteLine("正在导出PDF"); //打开prt Tag PartTag = Tag.Null; UFPart.LoadStatus ErrorStatus = new UFPart.LoadStatus(); theUfSession.Part.Open("D:\1.prt", out PartTag, out ErrorStatus); //导出pdf NXOpen.Part workPart = theSession.Parts.Work; NXOpen.PrintPDFBuilder printPDFBuilder1; printPDFBuilder1 = workPart.PlotManager.CreatePrintPdfbuilder(); printPDFBuilder1.Scale = 1.0; printPDFBuilder1.Size = NXOpen.PrintPDFBuilder.SizeOption.ScaleFactor; printPDFBuilder1.Units = NXOpen.PrintPDFBuilder.UnitsOption.English; printPDFBuilder1.XDimension = 8.5; printPDFBuilder1.YDimension = 11.0; printPDFBuilder1.OutputText = NXOpen.PrintPDFBuilder.OutputTextOption.Polylines; printPDFBuilder1.RasterImages = true; NXOpen.NXObject[] sheets1 = new NXOpen.NXObject[1]; NXOpen.Drawings.DrawingSheet drawingSheet1 = (NXOpen.Drawings.DrawingSheet)workPart.DrawingSheets.FindObject("Sheet 1"); sheets1[0] = drawingSheet1; printPDFBuilder1.SourceBuilder.SetSheets(sheets1); printPDFBuilder1.Filename = "D:\2\" + args[0].ToString() + ".pdf";//通过main函数传入参数 NXOpen.NXObject nXObject1; nXObject1 = printPDFBuilder1.Commit(); printPDFBuilder1.Destroy(); //关闭prt theUfSession.Part.Close(theSession.Parts.Display.Tag,1,1); theProgram.Dispose(); } catch (NXOpen.NXException ex) { // ---- Enter your exception handling code here ----- } return retValue; } //------------------------------------------------------------------------------ // Following method disposes all the class members //------------------------------------------------------------------------------ public void Dispose() { try { if (isDisposeCalled == false) { //TODO: Add your application code here } isDisposeCalled = true; } catch (NXOpen.NXException ex) { // ---- Enter your exception handling code here ----- } } } Caesar卢尚宇 2020年10月6日
2.调用exe(C#控制台项目)
主线程
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Threading; namespace ConsoleApplication2 { class Program { static void Main(string[] args) { Console.WriteLine("程序开始执行 "); System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); watch.Start(); //开始监视代码运行时间 MyCounter counter = new MyCounter(); MyCounterA counterA = new MyCounterA(); MyCounterB counterB = new MyCounterB(); Thread t = new Thread(new ThreadStart(counter.Run)); t.Start(); Thread tA = new Thread(new ThreadStart(counterA.Run)); tA.Start(); Thread tB = new Thread(new ThreadStart(counterB.Run)); tB.Start(); for (int i = 0; i < 5; i++) { //调用exe创建块 System.Diagnostics.Process exep1 = System.Diagnostics.Process.Start("D:\TestCode\NX11_Open_CS_Wizard4\NX11_Open_CS_Wizard4\bin\Debug\NX11_Open_CS_Wizard4.exe", i.ToString()+"A"); exep1.WaitForExit();//等待外部程序退出后才能往下执行 } watch.Stop(); //停止监视 TimeSpan timespan = watch.Elapsed; //获取当前实例测量得出的总时间 Console.WriteLine("程序结束" + ",代码执行时间:{0}(毫秒)", timespan.TotalMilliseconds);//总毫秒数 } } } Caesar卢尚宇 2020年10月6日
线程1
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Threading; namespace ConsoleApplication2 { class MyCounter { public void Run() { for (int i = 0; i < 5; i++) { //调用exe创建块 System.Diagnostics.Process exep1 = System.Diagnostics.Process.Start("D:\TestCode\NX11_Open_CS_Wizard4\NX11_Open_CS_Wizard4\bin\Debug\NX11_Open_CS_Wizard4.exe", i.ToString() + "B"); exep1.WaitForExit();//等待外部程序退出后才能往下执行 } } } } Caesar卢尚宇 2020年10月6日
线程2
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApplication2 { class MyCounterA { public void Run() { for (int i = 0; i < 5; i++) { //调用exe创建块 System.Diagnostics.Process exep1 = System.Diagnostics.Process.Start("D:\TestCode\NX11_Open_CS_Wizard4\NX11_Open_CS_Wizard4\bin\Debug\NX11_Open_CS_Wizard4.exe", i.ToString() + "C"); exep1.WaitForExit();//等待外部程序退出后才能往下执行 } } } } Caesar卢尚宇 2020年10月6日
线程3
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApplication2 { class MyCounterB { public void Run() { for (int i = 0; i < 5; i++) { //调用exe创建块 System.Diagnostics.Process exep1 = System.Diagnostics.Process.Start("D:\TestCode\NX11_Open_CS_Wizard4\NX11_Open_CS_Wizard4\bin\Debug\NX11_Open_CS_Wizard4.exe", i.ToString() + "D"); exep1.WaitForExit();//等待外部程序退出后才能往下执行 } } } } Caesar卢尚宇 2020年10月6日
3.速度对比动画
1.四个线程导出20张pdf
2.一个线程导出20张pdf
在速度上,肉眼就已经可以看出差距了。
4.补充
1.想要每次调用exe不弹出控制台窗口的话,可以使用下面这种方式调用。
for (int i = 0; i < 20; i++) { //调用exe创建块 System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo("D:\TestCode\NX11_Open_CS_Wizard4\NX11_Open_CS_Wizard4\bin\Debug\NX11_Open_CS_Wizard4.exe", i.ToString()+"A"); //设置不在新窗口中启动新的进程 startInfo.CreateNoWindow = true; //不使用操作系统使用的shell启动进程 startInfo.UseShellExecute = false; //将输出信息重定向 startInfo.RedirectStandardOutput = true; System.Diagnostics.Process process = System.Diagnostics.Process.Start(startInfo);; process.WaitForExit(); }
2.有些调用的exe是不需要阻塞等待的,就不需要用process.WaitForExit();这句了,速度上能更快些。
如果有些需要等调用exe,等待exe执行完的内容的,就需要阻塞等待了。等exe结束了,在执行下面的操作。
Caesar卢尚宇
2020年10月6日