Hello everyone,
i have got a problem with AutoCAD 2010 right now. Im having some procedures that take very long to process in between a TransactionManager.StartTransaction and Commit/Abort.
When taking too long AutoCAD sometimes just disappears/crashes without giving a call stack/Exception or anything. There are also no memory leaks or exceptions raised, though i send some status messages to the command line of AutoCAD.
Does AutoCAD need anything like a KeepAlive? Do i have to send it some specific messages or anything? Is that a common problem?
Hi,
Please show the code, and any other relevant information like platform, VS version, .NET Framework, drawing size (posting a sample dwg is very useful) , etc.
Gaston Nunez
Sadly i can not provide the drawing, because it crashes where the drawing gets generated.
VS-Version: 2008 C# Standard
.NET: 3.5
And here is the C# code(modified though):
using (Transaction acTransaction = TransactionManager.StartTransaction()) { try { CurrentTransaction = acTransaction; BlockTableRecord acBlockTableRecord = acTransaction.GetObject(BlockIds.Peek(), OpenMode.ForWrite) as BlockTableRecord; // Create a new object Region acRegion = GetProfileRegion(profile); Polyline3d acPath = GetExtrusionPath(profile.Axis); Solid3d acSolid = new Solid3d(); acSolid.SetDatabaseDefaults(); acSolid.ExtrudeAlongPath(acRegion, acPath, 0); Solid3d acSlicedSolid = acSolid; try { SolidAnalyzer.GetFaceNormals(profile, acSolid); } finally { if (acSlicedSolid != null) acSlicedSolid.Color = Autodesk.AutoCAD.Colors.Color.FromColor(profile.OuterColor); } // Append the newly created object to model space and active transaction acBlockTableRecord.AppendEntity(acSlicedSolid); acTransaction.AddNewlyCreatedDBObject(acSlicedSolid, true); acRegion.Dispose(); acPath.Erase(); // Save changes to database and close transaction acTransaction.Commit(); AutoCADApplication.Print("Profile: " + profile.Name + " successfully constructed."); } catch (Autodesk.AutoCAD.Runtime.Exception ex) { AutoCADApplication.Print("Failed to construct profile " + profile.Name + "\n" + ex.Message + "\n\n" + ex.StackTrace); acTransaction.Abort(); } finally { CurrentTransaction = null; }
The GetProfileRegion and GetExtrusionPath Methods always work/never crashed before and i can´t post them for different reasons. The profile region is a highly detailed cut of a window profile.
The SolidAnalyzer class is defined as follows:
public static class SolidAnalyzer { private static string Vector3dToString(Vector3d vector) { return "[" + vector.X.ToString("F2") + ", " + vector.Y.ToString("F2") + ", " + vector.Z.ToString("F2") + "]"; } private static Vector3d GetFaceNormal(Autodesk.AutoCAD.BoundaryRepresentation.Face face, Point3d point) { PointOnSurface ptOnSurf = face.Surface.GetClosestPointTo(point); Point2d param = ptOnSurf.Parameter; Vector3d normal = ptOnSurf.GetNormal(param); Vector3d normalTest = normal.MultiplyBy(1E-6 / normal.Length); Point3d ptTest = point.Add(normalTest); PointContainment ptContainment = new PointContainment(); bool reverse = false; using(BrepEntity brepEnt = face.Brep.GetPointContainment(ptTest, out ptContainment)) { if(ptContainment != PointContainment.Outside) { reverse = true; } } return normal.MultiplyBy(reverse ? -1.0 : 1.0); } public static List<Vector3d> GetFaceNormals(Profile profile, Solid3d profileSolid) { List<Vector3d> faceNormals = new List<Vector3d>(); using (Brep brep = new Brep(profileSolid)) { foreach (Autodesk.AutoCAD.BoundaryRepresentation.Face face in brep.Faces) { PointContainment ptContainment = new PointContainment(); using (BrepEntity brepEnt = face.GetPointContainment(new Point3d(0, 0, 0), out ptContainment)) { faceNormals.Add(GetFaceNormal(face, new Point3d(0, 0, 0))); //if (ptContainment == PointContainment.Inside || // ptContainment == PointContainment.OnBoundary) { AutoCADApplication.Print("\nFace Normal at " + "[0, 0, 0] = " + Vector3dToString(GetFaceNormal(face, new Point3d(0, 0, 0)))); } } } } return faceNormals; } }
After adding the SolidAnalyzer class and using GetFaceNormals AutoCAD sometimes first freezes/does not respond and then crashes or disappears after some normals have been written to the commandline.
This procedure takes very long because the solid3d has >300 faces most of the time.
I have not run your code to test what's going on exactly, but i can guess just looking... Please see my comments below...
using (Transaction acTransaction = TransactionManager.StartTransaction())
{
try
{
CurrentTransaction = acTransaction;
BlockTableRecord acBlockTableRecord = acTransaction.GetObject(BlockIds.Peek(),
OpenMode.ForWrite) as BlockTableRecord;
// Fenton : you must dispose all AutoCAD objects before
// this function goes out of scope, use using. Otherwise those objects will be disposed by the GC on a worker thread, which will most likely crash AutoCAD
using (Region acRegion = GetProfileRegion(profile))
{
using (Polyline3d acPath = GetExtrusionPath(profile.Axis))
{
using (Solid3d acSolid = new Solid3d())
{
acSolid.SetDatabaseDefaults();
acSolid.ExtrudeAlongPath(acRegion, acPath, 0);
// Fenton: what does this line mean? if you are trying
// to make a copy, think again because it won't
//Solid3d acSlicedSolid = acSolid;
// Fenton: this is better
Solid3d acSlicedSolid = new Solid3d();
acSlicedSolid.CopyFrom(acSolid);
try
{
SolidAnalyzer.GetFaceNormals(profile, acSolid);
}
finally
{
if (acSlicedSolid != null)
acSlicedSolid.Color = Autodesk.AutoCAD.Colors.Color.FromColor(profile.OuterColor);
}
// Append the newly created object to model space and active transaction
acBlockTableRecord.AppendEntity(acSlicedSolid);
acTransaction.AddNewlyCreatedDBObject(acSlicedSolid, true);
acPath.Erase();
}
}
}
// Save changes to database and close transaction
acTransaction.Commit();
AutoCADApplication.Print("Profile: " + profile.Name + " successfully constructed.");
}
catch (Autodesk.AutoCAD.Runtime.Exception ex)
{
AutoCADApplication.Print("Failed to construct profile " + profile.Name
+ "\n" + ex.Message + "\n\n" + ex.StackTrace);
acTransaction.Abort();
}
finally
{
CurrentTransaction = null;
}
I also just posted this for you guys...
http://adndevblog.typepad.com/autocad/2012/07/forcing-the-gc-to-run-on-the-main-thread.html
Thanks, Fenton.
The line where it says acSlicedSolid= ... was just a remain of a slicing procedure i commented out to test, sadly i forgot that line. It wasn´t intended to copy anything, it´s not a struct. Was used to determine which Solid3d to be cut because it was cut multiple times and that one was just a pointer to it.
Anyways, the GC won´t collect them in this case cause the objects are still referenced and using "using" doesn´t solve it either. I´ve just splitted it into multiple small transactions now and somehow it works.
I can´t really tell why though..., thanks a lot for the help.
No problem.
If you post a working sample project, I'll take a look at it for you.
Can't find what you're looking for? Ask the community or share your knowledge.