Random crash after executing ODTable Copy

Random crash after executing ODTable Copy

Anonymous
Not applicable
922 Views
2 Replies
Message 1 of 3

Random crash after executing ODTable Copy

Anonymous
Not applicable

Dear Support/Users!

 

I have a big problem that i tried to solve many times but without succes. I will include a part of my code, but first indroduce my program, so you understand what im doing. 

There are lines, lwpolylines and 3d polylines in our electric network map, we need to create a securety zone, a buffer of sort. But that is not all, these lines have object table attached, and these tables must be copied to the zones (lwpolylines). 

In short, i made functions that take these lines in, extracts the vertecies, it calculates the point of the zone, and returns a List<List<Point2d>>, so a list that contains a List of 2d points, from these points i create polylines. This part of the proccess works fine, exept, i have to turn visibility on manually, otherwise the zones wont be visible, until i open the drawing again.

here comes the problem to be solved:

The problem comes, when i attach or copy object data to the zones. If i do this with about 100-200 objects it works fine, i can do it again and again, without any problem. However if i do it with the whole drawing (2000+ objects) after the second time i do it it crashes, but not every time it seems to be random. Sometimes it occurs on the first try.

The errors:

fatal error unhandled access violation reading 0x0000 exception at ...

r6025 pure virtual function call...

If i try to debug, the crash doesnt happen in my code, if i recal correctly it is in the ManagedMapApi.dll and i dont know what is causing the problem.

If i run the program without the od table part it doesnt crash.

szelesseg = width of the zone.

metamasol = it is a bool value, the user can select if he wants to copy odtable or not

 

Here is the code:

[CommandMethod("zone_draw")]
public void test()
{
Document acDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
acDoc.LockDocument();
Database acCurDb = acDoc.Database;
Editor ed = acDoc.Editor;
Stopwatch sw;
PromptSelectionOptions pso = new PromptSelectionOptions();
pso.MessageForAdding = "\nVálaszd ki a nyomvonalakat amire biztonsági övezetet szeretnél rajzolni!";
double szelesseg;
GeneralFunc.CreateLayer("zone", 7);
ObjectIdCollection objcol = new ObjectIdCollection();
List<double> szellist = new List<double>();
PromptSelectionResult pres = ed.GetSelection(this.NyomvonalFilter());
if (pres.Status == PromptStatus.OK)
{
List<Tuple<ObjectId, ObjectId>> nyvesovezet = new List<Tuple<ObjectId, ObjectId>>();
List<double> szelessegek = new List<double>();
using (Transaction tr = acCurDb.TransactionManager.StartTransaction())
{
sw = new Stopwatch();
sw.Start();
BlockTable blktable = tr.GetObject(acCurDb.BlockTableId, OpenMode.ForRead) as BlockTable;
BlockTableRecord tblrec = tr.GetObject(blktable[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
List<List<Point2d>> biztovpoints = new List<List<Point2d>>();
SelectionSet ss = pres.Value;

bool canbedrawn = false;
for (int i = 0; i < ss.Count; i++)
{
Entity ent = tr.GetObject(ss[i].ObjectId, OpenMode.ForRead) as Entity;
if (VlancMegfelelo(ent.ObjectId, tr))
{
szelesseg = SzelessegMegad(ent.Layer);
if (ent.ObjectId.ObjectClass.DxfName == "LWPOLYLINE")
{

Polyline pl = ent as Polyline;

if (BiztonsagiOV(pl, szelesseg, out biztovpoints))
{
canbedrawn = true;
}
}
else if (ent.ObjectId.ObjectClass.DxfName == "LINE")
{
Line pl = ent.Clone() as Line;


if (BiztonsagiOV(pl as Line, szelesseg, out biztovpoints))
{
canbedrawn = true;
}
}
else //polyline
{
Polyline3d pl = ent as Polyline3d;

if (BiztonsagiOV(pl as Polyline3d, szelesseg, tr, out biztovpoints))
{
canbedrawn = true;
}
}

if (canbedrawn)
{
for (int j = 0; j < biztovpoints.Count; j++)
{
using (Polyline pline = new Polyline(biztovpoints.ElementAt(j).Count))
{

pline.SetDatabaseDefaults();

for (int k = 0; k < biztovpoints.ElementAt(j).Count; k++)
{
pline.AddVertexAt(k, biztovpoints.ElementAt(j).ElementAt(k), 0, 0, 0);

}

pline.Layer = folia;

tblrec.AppendEntity(pline);
tr.AddNewlyCreatedDBObject(pline, true);

nyvesovezet.Add(new Tuple<ObjectId, ObjectId>(ss[i].ObjectId, pline.ObjectId));
szelessegek.Add(szelesseg);

}
}


}

}
else
{
Entity e = tr.GetObject(ent.ObjectId, OpenMode.ForWrite) as Entity;
e.ColorIndex = 1;
}
}
tr.Commit();
}
using (Transaction tr = acCurDb.TransactionManager.StartTransaction())
{
for (int i = 0; i < nyvesovezet.Count; i++)
{
Entity id = tr.GetObject(nyvesovezet.ElementAt(i).Item2, OpenMode.ForWrite) as Entity;
if (metaMasol) CopyMetaData(nyvesovezet.ElementAt(i).Item1, nyvesovezet.ElementAt(i).Item2);

}
tr.Commit();
}
nyvesovezet.Clear();
sw.Stop();
ed.WriteMessage("\nA biztonsági öv meg lett rajzolva: " + sw.ElapsedMilliseconds + " msec alatt.");
}

 

public Dictionary<string, string> GetMetaData(ObjectId objid)
{
Dictionary<string, string> tablaertek = new Dictionary<string, string>();
Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
doc.LockDocument();
Autodesk.Gis.Map.ObjectData.Tables tables = Autodesk.Gis.Map.HostMapApplicationServices.Application.ActiveProject.ODTables;
Autodesk.Gis.Map.ObjectData.Table table = tables["EL_META"];
Editor ed = doc.Editor;
using (Records records = table.GetObjectTableRecords(0, objid, Autodesk.Gis.Map.Constants.OpenMode.OpenForRead, false))
{

if (records.Count == 0)
{
records.Dispose();
}
else
{
foreach (Record record in records)
{

if (record.TableName == "EL_META")
{

for (int i = 0; i < record.Count; i++)
{
FieldDefinitions tableDef = table.FieldDefinitions;
FieldDefinition column = null;
column = tableDef[i];
string colName = column.Name;
Autodesk.Gis.Map.Utilities.MapValue val = record[i];
string value = val.StrValue;
if (!tablaertek.ContainsKey(colName))
{
if (column.Type.ToString() == "Character")
{
tablaertek.Add(colName, val.StrValue);
}
else if (column.Type.ToString() == "Integer")
{
tablaertek.Add(colName, val.Int32Value.ToString());
}
else
{
tablaertek.Add(colName, val.DoubleValue.ToString());
}
}
else
{
break;
}
}
table.Dispose();
break;
}
}
records.Dispose();
}
}
return tablaertek;
}

public void AttachMetaTable(ObjectId objid) //there is no meta data in the object since it is newly created
{

Tables tables = HostMapApplicationServices.Application.ActiveProject.ODTables;
Autodesk.Gis.Map.ObjectData.Table table = tables["EL_META"];
Record Rec = Record.Create();

table.InitRecord(Rec);
table.AddRecord(Rec, objid);
}

public void CopyMetaData(ObjectId baseobject, ObjectId TargetObject)
{
Dictionary<string, string> tablaertek = GetMetaData(baseobject);
AttachMetaTable(TargetObject);
Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
doc.LockDocument();
if (tablaertek.Count != 0)
{

Autodesk.Gis.Map.ObjectData.Tables tables = Autodesk.Gis.Map.HostMapApplicationServices.Application.ActiveProject.ODTables;
Autodesk.Gis.Map.ObjectData.Table table = tables["EL_META"];
using (Records records = table.GetObjectTableRecords(0, TargetObject, Autodesk.Gis.Map.Constants.OpenMode.OpenForWrite, false))
{
if (records.Count == 0)
{
records.Dispose();
}
else
{

foreach (Record Recd in records)
{

if (Recd.TableName == "EL_META")
{
for (int i = 0; i < Recd.Count; i++)
{

FieldDefinitions tblDefs = table.FieldDefinitions;
FieldDefinition column = null;
column = tblDefs[i];
if (tablaertek.ContainsKey(column.Name))
{
Recd[i].Assign(tablaertek[column.Name]);
records.UpdateRecord(Recd);
}
}
table.Dispose();
break;
}

}
}

}
}
tablaertek.Clear();
}

 

 

I tried to attach od in the first transaction with entlast but didnt work, the problem was still there. Tried disposing entities, used the using statement on the created polyline. 

0 Likes
Accepted solutions (1)
923 Views
2 Replies
Replies (2)
Message 2 of 3

Anonymous
Not applicable

Okay, I changed the OD copy and adding function. I made this instead of the two:

 

public bool CopyODTable(string tablename, ObjectId baseObj, ObjectId targetobj)
{
      Autodesk.Gis.Map.ObjectData.Tables tables =         Autodesk.Gis.Map.HostMapApplicationServices.Application.ActiveProject.ODTables;
    Autodesk.Gis.Map.ObjectData.Table table = tables[tablename];

using (Records records = table.GetObjectTableRecords(0, baseObj, Autodesk.Gis.Map.Constants.OpenMode.OpenForRead, false))
{
    if (records.Count > 0)
    {
       Record Rec = records[0].Clone() as Record;
       table.AddRecord(Rec, targetobj);
       return true;
   }
else
{
   return false;
}
}
}

 

This way i thinks there should be no problem with the copy proccess. It works fine, and after I try to create the zones again on all objects it crashes with pure virtual function call.

I can think of two possibilities:

Autocad is starting something in the background, and the more elements i create the more time it needs, and after using my program again it isnt finished, and somehow they collide.

My second tought is that my program doesnt free up something, and in the second run i the Autocads methods cant open something for write. 

0 Likes
Message 3 of 3

Anonymous
Not applicable
Accepted solution

Maybe i was impatient, today i could solve, the problem. The reason for the crash is still unknown to me, but at least i got it working.

Copying OD tables between objects is something i did not encounter on the internet, so im gonna share my code, with this, and a lot of using statements and .dispose() functions i could reduce the speed of my program from 70 seconds to 4 seconds. (of course this depends on the objects, this is the result from my test dwg)

 

I think the main problem was putting "Autodesk.Gis.Map.HostMapApplicationServices.Application.ActiveProject.ODTables" into a variable, if i dispose this variable, then attaching od tables in the drawing is not possible. So i thought then i use it directly and dont use a variable.

 

public bool CopyODTable(string tablename, ObjectId baseObj, ObjectId targetobj)
{
 try
{
Autodesk.Gis.Map.ObjectData.Table table =               Autodesk.Gis.Map.HostMapApplicationServices.Application.ActiveProject.ODTables[tablename];
using (Records records = table.GetObjectTableRecords(0, baseObj,    Autodesk.Gis.Map.Constants.OpenMode.OpenForRead, false))
{
if (records.Count > 0 && records.Count < 2)
{
Record Rec = records[0].Clone() as Record;
table.AddRecord(Rec, targetobj);
records.Dispose();
Rec.Dispose();
table.Dispose();
return true;
}
else
{
records.Dispose();
table.Dispose();
return false;
}

}

}
catch
{
return false;
}
}

 

0 Likes