Class Objects seem to "time out" if VBA Forms / App left open, why?

mdlueck

Sr. Application Developer
Local time
Today, 14:12
Joined
Jun 23, 2011
Messages
2,649
Greetings,

I am seeing Access 2007 do something quite perplexing... The application I am developing makes use of Class Objects. These objects remain open during application execution and contain various state information about the application.

At times I will be debugging things and all of a sudden, deep into the application, objects which should have been in existence based on the running context of the application are being created and thus the proper context attributes are not contained in their attributes.

One object is the user authorization credentials. In that case, the ID becomes 0, which there is no 0 ID. All other attributes are also blanked. Net result, operations end up being logged that ID=0 did them.

Like wise, multiple screens deep into the application, if prior screen's objects are reset, then no longer do those objects have the context that subsequent objects / DB records should be associated with.

I have thought that perhaps some sort of reset happens if I use the debugger to trace program execution. However it happened again this morning, and I have not been debugging this morning.

The other thought is there is some sort of life span time out for these objects... that if the Access 2007 app is left idling for a while, then the objects expire. I did leave my desk for a few minutes this morning! (gasp!) :eek:

This sort of thing is quite disturbing. Does anyone have insight to this sort of behavior / know the specific details of when Access does this / workarounds to prevent such?

TIA!
 
P.S. And if I exit the application, restart, and plow-right-through the screens then the objects remain in existence and everything works properly.

Thus my two thoughts of what might be triggering this behavior were:
1) Using the Debugger
2) Leaving the app open and several forms deep into the UI, then coming back to work further with it

As of this morning I am now leaning more towards #2, which will not be acceptable to the client.
 
This kind of behaviour happens when an error occurs, especially when it occurs in a function or sub where the object or variable is referenced or used.

If you have proper error handling in place (in all your functions/subs) references to objects should remain.
 
If you have proper error handling in place (in all your functions/subs) references to objects should remain.

The only place I have skimped is if a form sub is making a one line call to a shared code func / sub, then I have sometimes skipped the error handling there as the shared code handles its own error handling... and I thought no need to protect a simple call to a shared code API.

As it happens when I am several screens into the app, then if I "Close / Close" to get back out, immediately I can see that the auth object was reset as buttons which were enabled for my ID are now disabled meaning that the permmask in the auth object is 0.

So definitely I am not seeing an error trigger it, leaning in the direction of "leaving the app idle for a period of time".
 
Yep, error handling will sort that out.

What you can do is set a Watch to see when the object gets reset. That will point to the instance when that reset is happening.
 
Yep, error handling will sort that out.

Will sort what out?!

This morning I left my app open a few screens deep, came back, issued "Close / Close" and started noticing buttons were disabled, meaning that the auth object got reset.

The close buttons have proper error handling as they are more complicated than simply forwarding a call to some shared code.

The type of code I did not specifically error handle was for example Double Click on a multi-record list forwards the event to the correct button. The button code has error handling, the Double Click is where I skimped.
 
I can't tell you all instances of where an object loses it's value but the most common one is On Error Resume Next which doesn't deal with the error. This is a misconstrued way of error handling which should be avoided at any cost.

Like I mentioned, all functions/subs must have proper error handling. Also, I mentioned setting a Watch on the object to see when it gets reset.
 
but the most common one is On Error Resume Next which doesn't deal with the error. This is a misconstrued way of error handling which should be avoided at any cost.

I do not use On Error Resume Next.

I have been coding my VBA error protected code as follows:

Code:
Private Sub fldtitle_DblClick(Cancel As Integer)
  On Error GoTo Err_fldtitle_DblClick

  'Send the command to the btnSelect pushbutton control Click() event...
  Call btnSelect_Click

Exit_fldtitle_DblClick:
  Exit Sub

Err_fldtitle_DblClick:
  Call errorhandler_MsgBox("Form: Form_projects, Subroutine: fldtitle_DblClick()")
  Resume Exit_fldtitle_DblClick

End Sub
Example of code where I do not have error handling at the Form level, but the shared code does the proper error handling. (As just above...)

Code:
Private Sub fldtitle_GotFocus()

  Call uiutils_GridSetSelectedRowBackgrond(Me)

End Sub
And another example...

Code:
Private Sub Label_title_Click()
  
  Call uiutils_SetFormSort(Me, "title", strSortColListArray(), strSQLinit, strCurrentSort)

End Sub
So you are saying I must put error handling as I have in my first example EVERYWHERE else risk Access/VBA dropping my objects from time to time?!?! Very odd... :confused:
 
Yes, any calls to other functions should also be error handled. There's no Throw/Catch in vba so error handling has to be there everywhere. There are times when an error is thrown in your call function, for example when you open a report and cancel it On No Data, you trap inside the function, not in the On No Data event.

I know it's a pain but it just can't be avoided in VBA.

Have you done the trace yet?
 
I know it's a pain but it just can't be avoided in VBA.

(sigh...)

Have you done the trace yet?

Trace of the objects resetting? No. Like I said, it seems to happen either with debugging or with letting the app idle for a long time. I did no debugging this morning, so I am leaning towards leaving the app idle is causing the condition. Next opportunity will be during lunch.

So for my global shared objects, just have them all being watched in the debugger, come back from lunch. Click the "Close" button, have the debugger turned on for the close button, and see how many objects have reset themselves?
 
Correct! So what you do is set it to Break when Value changes to 0. Run a sequence of events that you know will cause the objects to get reset and see when it breaks.
 
Correct! So what you do is set it to Break when Value changes to 0.

A break point which is watching the value of a variable? I have not seen such in VBA. Only break points which are at fixed spots in the code. Please enlighten me.

Run a sequence of events that you know will cause the objects to get reset and see when it breaks.

"Hopefully merely going to lunch and leaving it idle several Forms into the app."

Thanks,
 
A break point which is watching the value of a variable? I have not seen such in VBA. Only break points which are at fixed spots in the code. Please enlighten me.

Oh, I did not notice the additional options of the Watch setup window. Seems it is right in there. I will try to figure those other types of Watches out in VBA. Thanks
 
Debug > Add Watch. See attached.

You can put an expression like, SomeVariable = 0 and it will break when that condition is met.
 

Attachments

  • Watch.png
    Watch.png
    12.1 KB · Views: 131
Oh, I did not notice the additional options of the Watch setup window. Seems it is right in there. I will try to figure those other types of Watches out in VBA. Thanks
Looks like you figured it out. See how it goes.
 
I set up to Watch all of my global class object instances.

I do not seem to be able to get it to correctly Watch one specific variable / attribute of the class.

For example I have the watch of the Auth object. I can see all of its attributes when I expand that object into the tree view.

If I go to the line of code which defines one of the attributes, watch that variable, then I am always shown that it is out of context... as watching the bare variable. Yet just above in the watches window is the class object with all attributes correctly showing values.

Hint please at how to single out a class attribute and place your suggested value change watch on it?
 
I think you can only watch an instance of the object, not the entire object.

So if an instance of your Auth class was called instAuth, and you have some a Get property called ID, you will only be able to watchinstAuth.ID. However, you might be able to watch the individual objects, just give it a try.

If the watch window shows Out of Context when you setup the watch, just ignore it.
 
So if an instance of your Auth class was called instAuth, and you have some a Get property called ID, you will only be able to watchinstAuth.ID.

That worked. object.attribute was the correct Rx to Watch one attribute of an object.

40 mins for lunch, and the FE DB objects survived beautifully. I had not left my desk this morning for even half that and "the error" happened. (sigh...) This is going to be a hard one to track down.

Perhaps I did change code this morning, not remember I did, and that caused Access/VBA to loose the objects.
 
A good start will be to ensure that all functions/subs that make use of (i.e. set, let or get) that object/variable/instance is error handled.
 
Actually, I'd suggest the whole reason why objects reset is due to the fact that when you are debugging, you may have inadvertently reset the project which causes everything to reset. If you ever have pressed the "Stop" button and/or clicked Ok to "This will reset your project", the objects will be dereferenced. I'd bet that you'll find that it'll work fine when you're are NOT debugging and thus potentially changing the state of your application.
 

Users who are viewing this thread

Back
Top Bottom