Author Topic: Save interception  (Read 4216 times)

0 Members and 1 Guest are viewing this topic.

trembre

  • Guest
Save interception
« on: October 09, 2012, 09:30:36 PM »
 I recently had an issue pop up with some of my code whereby the document/database events I chose to automatically fire off some functionality during drawing saving caused unexpected errors.

 Initially, I chose the following logic to hook up my events;
 
  • Upon initialisation, I hooked a DocumentCreated Event called OpenDrawingAction
  • OpenDrawingAction then hooked up a BeginSave event to the active database, called OnBeginSave, every time a drawing opened

 This worked as expected until an intermittent bug arose.  First off, it was noticed that when an autosave occurred, the OnBeginSave functionality always fired twice.  This wasn't a big issue until it was noted that if more than one drawing was open, the user switched back and forth between them and more autosaves took place, the OnBeginSave functionality now stopped working completely.  I tried to get to the bottom of why the double save occurred during autosaves, and why it seemingly blanked the save event hook-ups, but didn't really get anywhere. 

 As such, I tried some different event configurations and arrived at the following;
  • During initialisation, I still hook up my DocumentCreated event (though removed its BeginSave hook-up), but have added a DocumentLockModeChanged event
  • The DocumentLockModeChanged event now replaces the BeginSave functionality though is directed specifically at the QSAVE and SAVE commands when the lock mode is set to Write

 This alternative setup means autosave now no longer fires off the save functionality at all (which is good - the extended functionality involves asynchronous calls to doc control databases), and the functionality persists between multiple drawings/autosaves.  I'm posting this as a general heads-ups, and to see if anyone could explain what I was doing wrong intially and maybe possible pitfalls with my current approach.

 AutoCAD 2011 64bit, C#.NET, VS2010. 

 

TheMaster

  • Guest
Re: Save interception
« Reply #1 on: October 10, 2012, 01:22:27 AM »
I recently had an issue pop up with some of my code whereby the document/database events I chose to automatically fire off some functionality during drawing saving caused unexpected errors.

 Initially, I chose the following logic to hook up my events;
 
  • Upon initialisation, I hooked a DocumentCreated Event called OpenDrawingAction
  • OpenDrawingAction then hooked up a BeginSave event to the active database, called OnBeginSave, every time a drawing opened

 This worked as expected until an intermittent bug arose.  First off, it was noticed that when an autosave occurred, the OnBeginSave functionality always fired twice.  This wasn't a big issue until it was noted that if more than one drawing was open, the user switched back and forth between them and more autosaves took place, the OnBeginSave functionality now stopped working completely.  I tried to get to the bottom of why the double save occurred during autosaves, and why it seemingly blanked the save event hook-ups, but didn't really get anywhere. 

 As such, I tried some different event configurations and arrived at the following;
  • During initialisation, I still hook up my DocumentCreated event (though removed its BeginSave hook-up), but have added a DocumentLockModeChanged event
  • The DocumentLockModeChanged event now replaces the BeginSave functionality though is directed specifically at the QSAVE and SAVE commands when the lock mode is set to Write

 This alternative setup means autosave now no longer fires off the save functionality at all (which is good - the extended functionality involves asynchronous calls to doc control databases), and the functionality persists between multiple drawings/autosaves.  I'm posting this as a general heads-ups, and to see if anyone could explain what I was doing wrong intially and maybe possible pitfalls with my current approach.

 AutoCAD 2011 64bit, C#.NET, VS2010.

Never had it happen and I use the event all the time, so I'll assume that its an issue within your code.

trembre

  • Guest
Re: Save interception
« Reply #2 on: October 10, 2012, 01:51:25 AM »
 Certainly wouldn't rule that out, but the reason I checked to see if autosave was the problem was due to a suggestion from a former work colleague - he'd had a similar thing happen to him.  He theorised that the standard "DocumentManager.MdiActiveDocument.Database" methodology was grabbing the wrong database somewhow due to the autosave.

 The steps that brought about the error were as follows for anyone who wishes to humour me;
  • Open a drawing that has custom Database.BeginSave event functionality firing off and let it autosave
  • Open a second drawing
  • Switch back to your original drawing, again, let it autosave
  • Run qsave - at this point, my custom save functionality no longer works

TheMaster

  • Guest
Re: Save interception
« Reply #3 on: October 10, 2012, 02:25:40 AM »
Certainly wouldn't rule that out, but the reason I checked to see if autosave was the problem was due to a suggestion from a former work colleague - he'd had a similar thing happen to him.  He theorised that the standard "DocumentManager.MdiActiveDocument.Database" methodology was grabbing the wrong database somewhow due to the autosave.

 The steps that brought about the error were as follows for anyone who wishes to humour me;
  • Open a drawing that has custom Database.BeginSave event functionality firing off and let it autosave
  • Open a second drawing
  • Switch back to your original drawing, again, let it autosave
  • Run qsave - at this point, my custom save functionality no longer works

I've frequently seen bugs that result in an event handler being fired multiple times, because the handler was added to the same event source multiple times, and in the case of AutoCAD API events, it is often a result of adding events from the handler of another event that fires often, like the DocumentActivated event.

My guess, is that if your handler is firing multiple times, it is because it was added to the event multiple times, but without seeing some code, there's not really much anyone can do other than guess.

trembre

  • Guest
Re: Save interception
« Reply #4 on: October 10, 2012, 05:54:56 PM »
 I had the multiple firing issue come up with some of the alternative events I tried to use, but it didn't seem to be the same problem.  With the original problem, the multiple saving only occurred during an autosave, not during a normal save/qsave.

 Returning to the original problem code, the events were hooked up as such;
       
Code: [Select]
public void Initialize()
        {
            Application.DocumentManager.DocumentCreated += (new DocumentCollectionEventHandler(OnDrawingOpenAction));
        }

        void OnDrawingOpenAction(object sender, DocumentCollectionEventArgs OnDrawingOpenActionEvtArgs)
        {
            RunDrawingOpenAction();
        }

 RunDrawingOpenAction then hooks up the BeginSave routine;
Code: [Select]
public void RunDrawingOpenAction()
        {
            try
            {
                Database db = AcadApp.DocumentManager.MdiActiveDocument.Database;
                db.BeginSave += new DatabaseIOEventHandler(OnBeginSave);
                ....
            }
         }

OnBeginSave then fired off my extended functionality.
               

TheMaster

  • Guest
Re: Save interception
« Reply #5 on: October 10, 2012, 06:19:24 PM »
I had the multiple firing issue come up with some of the alternative events I tried to use, but it didn't seem to be the same problem.  With the original problem, the multiple saving only occurred during an autosave, not during a normal save/qsave.

 Returning to the original problem code, the events were hooked up as such;
       
Code: [Select]
public void Initialize()
        {
            Application.DocumentManager.DocumentCreated += (new DocumentCollectionEventHandler(OnDrawingOpenAction));
        }

        void OnDrawingOpenAction(object sender, DocumentCollectionEventArgs OnDrawingOpenActionEvtArgs)
        {
            RunDrawingOpenAction();
        }

 RunDrawingOpenAction then hooks up the BeginSave routine;
Code: [Select]
public void RunDrawingOpenAction()
        {
            try
            {
                Database db = AcadApp.DocumentManager.MdiActiveDocument.Database;
                db.BeginSave += new DatabaseIOEventHandler(OnBeginSave);
                ....
            }
         }

OnBeginSave then fired off my extended functionality.
               

Nothing in the code you show would result in the beginSave event firing multiple times, so there must be something else causing it. I would check the filename passed into the event arguments to see if it is different across notifications.

trembre

  • Guest
Re: Save interception
« Reply #6 on: October 10, 2012, 07:49:12 PM »
 Hmmm... it is something in my extended code, not the event hook-ups.  I wrote a small solution just firing the events and it behaved correctly.  How my extended code causes that glitch during autosaves and not regular saves will be something to explore, thanks for your input.

n.yuan

  • Bull Frog
  • Posts: 348
Re: Save interception
« Reply #7 on: October 11, 2012, 09:57:27 AM »
I had the multiple firing issue come up with some of the alternative events I tried to use, but it didn't seem to be the same problem.  With the original problem, the multiple saving only occurred during an autosave, not during a normal save/qsave.

 Returning to the original problem code, the events were hooked up as such;
       
Code: [Select]
public void Initialize()
        {
            Application.DocumentManager.DocumentCreated += (new DocumentCollectionEventHandler(OnDrawingOpenAction));
        }

        void OnDrawingOpenAction(object sender, DocumentCollectionEventArgs OnDrawingOpenActionEvtArgs)
        {
            RunDrawingOpenAction();
        }

 RunDrawingOpenAction then hooks up the BeginSave routine;
Code: [Select]
public void RunDrawingOpenAction()
        {
            try
            {
                Database db = AcadApp.DocumentManager.MdiActiveDocument.Database;
                db.BeginSave += new DatabaseIOEventHandler(OnBeginSave);
                ....
            }
         }

OnBeginSave then fired off my extended functionality.
               

Just a thought: since you hook the Database.BeginSave event handler to the MdiActiveDocument, you'd better be sure when a document becomes an MdiActiveDocument. In your code, obviously, you decided that it is when the DocumentCreated event is raised, which I am not quite certain and even in doubt. It may be the case when the document is the first document to open, but may not be true if there is already a document is opened: ini this case, even a new document is created, the MdiActiveDocuemnt may still points to the previous document until the newly created document became MdiActiveDocument (DocumentBecameCurrent event is raised).

As ObjectARX document suggested, we'd better not rely on the order of events being raised. At least, I think, you'd better do as Tony suggested, to compare the document names in the 2 evernts do see if you are hooking the event handler to correct document/database. You may want to keep a static document name list that you have already hooked the envent handlers, so that you would not duplicate.

TheMaster

  • Guest
Re: Save interception
« Reply #8 on: October 12, 2012, 01:30:37 PM »
I had the multiple firing issue come up with some of the alternative events I tried to use, but it didn't seem to be the same problem.  With the original problem, the multiple saving only occurred during an autosave, not during a normal save/qsave.

 Returning to the original problem code, the events were hooked up as such;
       
Code: [Select]
public void Initialize()
        {
            Application.DocumentManager.DocumentCreated += (new DocumentCollectionEventHandler(OnDrawingOpenAction));
        }

        void OnDrawingOpenAction(object sender, DocumentCollectionEventArgs OnDrawingOpenActionEvtArgs)
        {
            RunDrawingOpenAction();
        }

 RunDrawingOpenAction then hooks up the BeginSave routine;
Code: [Select]
public void RunDrawingOpenAction()
        {
            try
            {
                Database db = AcadApp.DocumentManager.MdiActiveDocument.Database;
                db.BeginSave += new DatabaseIOEventHandler(OnBeginSave);
                ....
            }
         }

OnBeginSave then fired off my extended functionality.
               

Well, I'll confess to not having looked closely enough at your code, and thanks to n.yaun for pointing it out.

The documentCreated event fires before the newly-created document is activated, and that's clearly a problem.

Use the document passed in the event argument, not the MdiActiveDocument.