As we know, we need to lock the AutoCAD document when trying to make changes to the database from the application context such as from a modeless dialog or from a COM server. We do not have to do so in the document context.
The question comes: what about locking the document when not necessary? Does it do any harm?
Let’s figure it out in this post. The following code and commands serve for this purpose.
[CommandMethod("LockDocumentTest4")]
public static void LockDocumentTest4_Method()
{
Editor ed = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor;
Document doc = MgdAcApplication.DocumentManager.MdiActiveDocument;
Database db = HostApplicationServices.WorkingDatabase;
PromptSelectionResult selRes = ed.SelectAll();
Stopwatch watch = new Stopwatch();
try
{
watch.Restart();
foreach (ObjectId id in selRes.Value.GetObjectIds())
{
ChangeEntityColorWithLock(id, 1);
}
watch.Stop();
ed.WriteMessage(string.Format("\nLockDocumentTest4: Lock Count:{0} Time:{1}", selRes.Value.Count, watch.Elapsed.TotalMilliseconds));
}
catch (System.Exception ex)
{
MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.WriteMessage(Environment.NewLine + ex.Message);
}
}
[CommandMethod("LockDocumentTest3")]
public static void LockDocumentTest3_Method()
{
Editor ed = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor;
Document doc = MgdAcApplication.DocumentManager.MdiActiveDocument;
Database db = HostApplicationServices.WorkingDatabase;
PromptSelectionResult selRes = ed.SelectAll();
Stopwatch watch = new Stopwatch();
try
{
watch.Restart();
foreach (ObjectId id in selRes.Value.GetObjectIds())
{
ChangeEntityColorWithoutLock(id, 2);
}
watch.Stop();
ed.WriteMessage(string.Format("\nLockDocumentTest3:NoLock Count:{0} Time:{1}", selRes.Value.Count, watch.Elapsed.TotalMilliseconds));
}
catch (System.Exception ex)
{
MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.WriteMessage(Environment.NewLine + ex.Message);
}
}
private static void ChangeEntityColorWithoutLock(ObjectId id, short color)
{
Database db = HostApplicationServices.WorkingDatabase;
using (Transaction dbTr = db.TransactionManager.StartTransaction())
{
Entity ent = dbTr.GetObject(id, OpenMode.ForWrite) as Entity;
ent.ColorIndex = color;
dbTr.Commit();
}
}
private static void ChangeEntityColorWithLock(ObjectId id, short color)
{
Database db = HostApplicationServices.WorkingDatabase;
using (MgdAcApplication.DocumentManager.MdiActiveDocument.LockDocument())
{
using (Transaction dbTr = db.TransactionManager.StartTransaction())
{
Entity ent = dbTr.GetObject(id, OpenMode.ForWrite) as Entity;
ent.ColorIndex = color;
dbTr.Commit();
}
}
}
[CommandMethod("LockDocumentTest2")]
public static void LockDocumentTest2_Method()
{
Editor ed = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor;
Document doc = MgdAcApplication.DocumentManager.MdiActiveDocument;
Database db = HostApplicationServices.WorkingDatabase;
int count = 0;
Stopwatch watch = new Stopwatch();
try
{
count = 0;
watch.Restart();
using (doc.LockDocument())
{
using (Transaction dbTr = db.TransactionManager.StartTransaction())
{
BlockTableRecord btr = (BlockTableRecord)dbTr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
foreach (ObjectId id in btr)
{
Entity ent = dbTr.GetObject(id, OpenMode.ForWrite) as Entity;
ent.ColorIndex = 2;
count++;
}
dbTr.Commit();
}
}
watch.Stop();
ed.WriteMessage(string.Format("\nLockDocumentTest2: Lock Count:{0} Time:{1}", count, watch.Elapsed.TotalMilliseconds));
}
catch (System.Exception ex)
{
MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.WriteMessage(Environment.NewLine + ex.Message);
}
}
[CommandMethod("LockDocumentTest1")]
public static void LockDocumentTest1_Method()
{
Editor ed = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor;
Document doc = MgdAcApplication.DocumentManager.MdiActiveDocument;
Database db = HostApplicationServices.WorkingDatabase;
int count = 0;
Stopwatch watch = new Stopwatch();
try
{
count = 0;
watch.Restart();
using (Transaction dbTr = db.TransactionManager.StartTransaction())
{
BlockTableRecord btr = (BlockTableRecord)dbTr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
foreach (ObjectId id in btr)
{
Entity ent = dbTr.GetObject(id, OpenMode.ForWrite) as Entity;
ent.ColorIndex = 1;
count++;
}
dbTr.Commit();
}
watch.Stop();
ed.WriteMessage(string.Format("\nLockDocumentTest1:NoLock Count:{0} Time:{1}", count, watch.Elapsed.TotalMilliseconds));
}
catch (System.Exception ex)
{
MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.WriteMessage(Environment.NewLine + ex.Message);
}
}
The first test command tries to change the color of all entities without locking the document. The second does pretty much the same except for locking the document instead. The third selects all entities first and change entity color through calling a method that locks the document first. The fourth calls a method that does not care about document locking to do the same thing.
Here is the output in one AutoCAD session without doing anything else except trying these commands in the exact order:
Command: LockDocumentTest1
LockDocumentTest1:NoLock Count:1663 Time:1403.843
Command: LOCKDOCUMENTTEST2
LockDocumentTest2: Lock Count:1663 Time:826.2279
Command: LOCKDOCUMENTTEST3
LockDocumentTest3:NoLock Count:1667 Time:24765.9259
Command: LOCKDOCUMENTTEST4
LockDocumentTest4: Lock Count:1667 Time:26985.5377
Command: LOCKDOCUMENTTEST4
LockDocumentTest4: Lock Count:1667 Time:26394.4141
Command: LOCKDOCUMENTTEST3
LockDocumentTest3:NoLock Count:1667 Time:30559.733
Command: LOCKDOCUMENTTEST2
LockDocumentTest2: Lock Count:1663 Time:1492.1513
Command: LOCKDOCUMENTTEST1
LockDocumentTest1:NoLock Count:1663 Time:926.3261
Here is the output in another AutoCAD session without doing anything else except trying these commands in the exact order:
Command: LockDocumentTest2
LockDocumentTest2: Lock Count:1663 Time:1634.7292
Command: LOCKDOCUMENTTEST1
LockDocumentTest1:NoLock Count:1663 Time:753.5942
Command: LOCKDOCUMENTTEST4
LockDocumentTest4: Lock Count:1667 Time:24731.3362
Command: LOCKDOCUMENTTEST3
LockDocumentTest3:NoLock Count:1667 Time:26789.0331
Command: LOCKDOCUMENTTEST1
LockDocumentTest1:NoLock Count:1663 Time:1501.3296
Command: LOCKDOCUMENTTEST2
LockDocumentTest2: Lock Count:1663 Time:804.7384
Command: LOCKDOCUMENTTEST3
LockDocumentTest3:NoLock Count:1667 Time:28481.1508
Command: LOCKDOCUMENTTEST4
LockDocumentTest4: Lock Count:1667 Time:28190.9131
Surprised by the result again, huh?
As can be seen, the performance of unnecessarily locking the AutoCAD document really depends. Some times, it is slower but some other times it can be quicker!
Doing an average work may make things clearer:
#1 #2 #3 #4 Average
Test1(NoLock) 1404 926 754 1501 1146
Test2(Lock) 826 1492 1635 805 1190
Test3(NoLock) 24766 30560 26789 28481 27649
Test4(Lock) 26986 26394 24731 28190 26575
So always locking documents does not really affect performance. It may increate the performance a little bit in some situations. However, from the sake of code efficiency and readability, it may be good to not lock documents in any help methods and add the call in their callers when necessary such as in an event callback of a modeless dialog or a COM server interface.
The leading edge AutoCAD .NET Addin Wizard (AcadNetAddinWizard) provides various project wizards, item wizards, coders and widgets to help program AutoCAD .NET addins.
Posted by: |