Author Topic: Document has a command in progress...  (Read 5262 times)

0 Members and 1 Guest are viewing this topic.

Andrey Bushman

  • Swamp Rat
  • Posts: 864
Document has a command in progress...
« on: August 02, 2010, 03:23:25 PM »
I write code,which must union 2 table styles. It work. But after work of code, if I run "_qsave" command - I get message: "Document has a command in progress...".
Screen:



But if I run other commands - I not get it message.

I can't find problem...

Code: [Select]
[CommandMethod("Q2", CommandFlags.Session)]
public void UnionTableStyles()
{
    string firstTableStyleName = "ts1";
    string secondTableStyleName = "ts2";

    lock (dwg.LockDocument())
    {
        using (Transaction t = dwg.TransactionManager.StartTransaction())
        {
            DBDictionary dict = (DBDictionary)t.GetObject(db.TableStyleDictionaryId, OpenMode.ForWrite);
            TableStyle ts1 = (TableStyle) t.GetObject((ObjectId)dict[firstTableStyleName], OpenMode.ForRead);
            TableStyle ts2 = (TableStyle)t.GetObject((ObjectId)dict[secondTableStyleName], OpenMode.ForRead);
                     
            List<ObjectId> primitives = new List<ObjectId>();

            if (db.Tablestyle == ts1.ObjectId) db.Tablestyle = ts2.ObjectId;

            for (long i = db.BlockTableId.Handle.Value; i < db.Handseed.Value; i++)
            {
                ObjectId id = ObjectId.Null;
                try
                {
                    id = db.GetObjectId(false, new Handle(i), 0);
                }
                catch (System.Exception)
                { continue; }
                if (!id.IsErased)
                {
                    DBObject x = t.GetObject(id, OpenMode.ForRead);
                    if (x is Table && ((Table)x).TableStyle == ts1.ObjectId)
                    {
                        primitives.Add(id);
                    }
                }
            }
            foreach (ObjectId id in primitives)
            {
                DBObject x = t.GetObject(id, OpenMode.ForWrite);
                Table table = (Table)x;
                table.TableStyle = ts2.ObjectId;
                x.DowngradeOpen();
            }                   
            ObjectIdCollection c = new ObjectIdCollection(new ObjectId[] { ts1.ObjectId });
            db.Purge(c);
            if (c.Count != 0) dict.Remove(ts1.ObjectId);
            t.Commit();
        }
    }
}

Glenn R

  • Guest
Re: Document has a command in progress...
« Reply #1 on: August 02, 2010, 03:31:34 PM »
What is the purpose of this line:

Code: [Select]
lock (dwg.LockDocument())

Andrey Bushman

  • Swamp Rat
  • Posts: 864
Re: Document has a command in progress...
« Reply #2 on: August 02, 2010, 03:48:52 PM »
What is the purpose of this line:

Code: [Select]
lock (dwg.LockDocument())
lock document while work my method (other users can't modify drawing).

without lock I get error (eLockViolation) in string:
Code: [Select]
DBDictionary dict = (DBDictionary)t.GetObject(db.TableStyleDictionaryId, OpenMode.ForWrite);

Glenn R

  • Guest
Re: Document has a command in progress...
« Reply #3 on: August 02, 2010, 04:01:45 PM »
I know what it is, I just wanted to see what you thought it was used for.
The correct usage is this:

Code: [Select]
using (DocumentLock yourVariableNameGoesHere = someVariableThatIsADocument.LockDocument())
{
  // some interesting code goes here
}

By using a 'using' statement, the DocumentLock is correctly disposed, which releases your document (which you code doesn't do), even in the event of failure.

Also, you should never be using the C# 'lock' keyword in AutoCAD, as it's for locking down code for multi-thread access, which AutoCAD is not capable of doing, using any of it's in-built functions.

Next question:

With the below attribute, why are you using CommangFlags.Session?
Code: [Select]
[CommandMethod("Q2", CommandFlags.Session)]

Andrey Bushman

  • Swamp Rat
  • Posts: 864
Re: Document has a command in progress...
« Reply #4 on: August 02, 2010, 04:26:46 PM »
I know what it is, I just wanted to see what you thought it was used for.
The correct usage is this:

Code: [Select]
using (DocumentLock yourVariableNameGoesHere = someVariableThatIsADocument.LockDocument())
{
  // some interesting code goes here
}

By using a 'using' statement, the DocumentLock is correctly disposed, which releases your document (which you code doesn't do), even in the event of failure.

Also, you should never be using the C# 'lock' keyword in AutoCAD, as it's for locking down code for multi-thread access, which AutoCAD is not capable of doing, using any of it's in-built functions
Thank you! Now all ok!

Next question:

With the below attribute, why are you using CommangFlags.Session?
Code: [Select]
[CommandMethod("Q2", CommandFlags.Session)]
Because it code may be use for batch processing (several drawing).

It was very simplified code (the original - differs).

Thank you for help!
« Last Edit: August 02, 2010, 04:31:32 PM by Hwd »

Glenn R

  • Guest
Re: Document has a command in progress...
« Reply #5 on: August 02, 2010, 04:35:46 PM »
Because it code may be use for batch processing (several drawing).

If that's the case, then you will need CommandFlags.Session. If you don't need to run from the Application context, then you don't use LockDocument and your command should be decorated with the CommanFlags.Modal attribute parameter.

Also, in future, if you want help from the members on this board, it is worth posting code that people can run. The code you posted wouldn't as there were things missing.

Andrey Bushman

  • Swamp Rat
  • Posts: 864
Re: Document has a command in progress...
« Reply #6 on: August 02, 2010, 04:43:10 PM »
Because it code may be use for batch processing (several drawing).
Also, in future, if you want help from the members on this board, it is worth posting code that people can run. The code you posted wouldn't as there were things missing.
Excuse me. It more full code:
Code: [Select]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Autodesk.AutoCAD.GraphicsInterface;
using Autodesk.AutoCAD.Interop.Common;
//Acad
using acad = Autodesk.AutoCAD.ApplicationServices.Application;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.LayerManager;
using Autodesk.AutoCAD.Colors;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Interop;

namespace Bushman.Autodesk.AutoCAD.Styles
{
    public class Class1
    {
        Document dwg;
        Editor ed;
        Database db;

        void Initialize()
        {
            dwg = acad.DocumentManager.MdiActiveDocument;
            ed = dwg.Editor;
            db = dwg.Database;
        }

        public Class1()
        {
            Initialize();
        }
       
        [CommandMethod("Q2", CommandFlags.Session)]
        public void UnionTableStyles()
        {
            string firstTableStyleName = "ts1";
            string secondTableStyleName = "ts2";
           
            using (dwg.LockDocument())
            {
                using (Transaction t = dwg.TransactionManager.StartTransaction())
                {
                    DBDictionary dict = (DBDictionary)t.GetObject(db.TableStyleDictionaryId, OpenMode.ForWrite);
                    TableStyle ts1 = (TableStyle) t.GetObject((ObjectId)dict[firstTableStyleName], OpenMode.ForRead);
                    TableStyle ts2 = (TableStyle)t.GetObject((ObjectId)dict[secondTableStyleName], OpenMode.ForRead);
                     
                    List<ObjectId> primitives = new List<ObjectId>();

                    if (db.Tablestyle == ts1.ObjectId) db.Tablestyle = ts2.ObjectId;

                    for (long i = db.BlockTableId.Handle.Value; i < db.Handseed.Value; i++)
                    {
                        ObjectId id = ObjectId.Null;
                        try
                        {
                            id = db.GetObjectId(false, new Handle(i), 0);
                        }
                        catch (System.Exception)
                        { continue; }
                        if (!id.IsErased)
                        {
                            DBObject x = t.GetObject(id, OpenMode.ForRead);
                            if (x is Table && ((Table)x).TableStyle == ts1.ObjectId)
                            {
                                primitives.Add(id);
                            }
                        }
                    }
                    foreach (ObjectId id in primitives)
                    {
                        DBObject x = t.GetObject(id, OpenMode.ForWrite);
                        Table table = (Table)x;
                        table.TableStyle = ts2.ObjectId;
                        x.DowngradeOpen();
                    }                   
                    ObjectIdCollection c = new ObjectIdCollection(new ObjectId[] { ts1.ObjectId });
                    db.Purge(c);
                    if (c.Count != 0) dict.Remove(ts1.ObjectId);
                    t.Commit();
                }
            }
        }
    }
}

If that's the case, then you will need CommandFlags.Session. If you don't need to run from the Application context, then you don't use LockDocument and your command should be decorated with the CommanFlags.Modal attribute parameter.
Thank you.

Glenn R

  • Guest
Re: Document has a command in progress...
« Reply #7 on: August 02, 2010, 04:46:01 PM »
You're welcome.

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4075
Re: Document has a command in progress...
« Reply #8 on: August 02, 2010, 05:51:06 PM »
Not to ask a dumb question, but if your in the drawing to run the code, why lock the dwg?  Isn't it already locked because your in it?
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

Glenn R

  • Guest
Re: Document has a command in progress...
« Reply #9 on: August 03, 2010, 05:43:32 AM »
That depends. Consider a modeless dialog - a palette is an excellent example. Because it's modeless, you will be running from the Application context, not in a drawing perse, so you will have to explicitly lock the document before you begin your mojo.

Contrast this to a command that has CommandFlags.Modal. This is running in the context of the drawing and a lock is implicitly applied by autocad, therefore, no need to lock it yourself.

I think of it as outside (application context) and inside (document context). If you're on the inside, you've got less to do - if you're on the outside looking in, you got more to do.

Andrey Bushman

  • Swamp Rat
  • Posts: 864
Re: Document has a command in progress...
« Reply #10 on: August 03, 2010, 06:10:31 AM »
That depends. Consider a modeless dialog - a palette is an excellent example. Because it's modeless, you will be running from the Application context, not in a drawing perse, so you will have to explicitly lock the document before you begin your mojo.

Contrast this to a command that has CommandFlags.Modal. This is running in the context of the drawing and a lock is implicitly applied by autocad, therefore, no need to lock it yourself.

I think of it as outside (application context) and inside (document context). If you're on the inside, you've got less to do - if you're on the outside looking in, you got more to do.
Thank you!

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4075
Re: Document has a command in progress...
« Reply #11 on: August 03, 2010, 09:05:34 AM »
That makes perfect sense, thanks Glenn
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)