Not actually a problem...
Hello friends.
I want to start a little discussion here about some issues which really intrigued me recently.
Some of you gurus keep going on about how you should Set myObjectVariable = Nothing before leaving a Sub or Function. I never did that and still live. So I made some tests with the following code fragment.
In the Sub CreateFSOAndDontCleanUp() you can choose any one of 4 methods to create a FileSystemObject, either locally or to a global variable in the form, and avoid setting the variable back to nothing.
Code:
Private FSO As New FileSystemObject
Private FSP As FileSystemObject
Private Sub CreateFSOAndDontCleanUp()
'1
'Dim f As New FileSystemObject
'2
Dim f As FileSystemObject
Set f = CreateObject("scripting.filesystemobject")
'3
'Set FSO = New FileSystemObject
'4
'Set FSP = New FileSystemObject
End Sub
Private Sub btnCleanUpTest_Click()
Static running As Boolean
Dim i%
running = Not running
'txtLoopCount.Text = 0
btnCleanUpTest.Caption = IIf(running, "Stop", "Don't Clean Up Test")
While running
For i = 1 To 1000
CreateFSOAndDontCleanUp
Next
txtLoopCount.Text = Val(txtLoopCount.Text) + 10000
DoEvents
Wend
End Sub
VB seems to be a very friendly language, indeed. It seems to clean up any locally created objects when leaving a sub or function. After creating millions of filesystemobjects there is still the full amount of memory available. Also when an object variable is assigned a new object, the old one seems to be destroyed automatically. So I don't see any point in setting an objVar back to Nothing.
To get an idea what was supposed to happen, I created an Array of 100000 FileSystemObjects. They consume about 3MByte of memory.
Altough I terminated the exe with the frowned upon "End" statement, all memory is freed properly. This another rumour, perhaps?
Please correct me if I'm missing something here.
(One observation I made herewith is, the CreateObject() method takes much longer to create an FSO than the New statement.)
The second thing I ran into came up when I went and posted code where I created a global FileSystemObject like
Code:
Public FSO as New FileSystemObject 'in a module
'or
Private FSO as New FileSystemObject 'in a Form
I was advised, not to do so, because for some reason or other it would be slower than an FSO created locally.
I checked this, too.
Taking the precise time to list about 1000 files from a folder with a for each fil in fold.files the global New FSO showed exactly the same time behaviour than a locally created FSO.
I have no idea how I could compare a "Dim AS New" FSO with a "Set FSO = New..." FSO from it's memory structure , otherwise I would have checked for differences.
Please, don't rip my head orf. :) Any comments or clarifications would be highly appreciated.
Re: Not actually a problem...
Might work, but it's bad practice. It would NOT work with Office Apps, and other types of objects.
Code:
Option Explicit
' These are both examples of Late Binding
Public Sub RunAccessMacro(strDB As String, strMacro As String)
'================================================================
'for late binding declare it As Object and use CreateObject() function
Dim AccessDB As Object
Set AccessDB = CreateObject("Access.Application")
With AccessDB
.OpenCurrentDatabase strDB
.DoCmd.RunMacro strMacro, 1
'.Visible = True 'you decide
.CloseCurrentDatabase
End With
Set AccessDB = Nothing
End Sub
Public Sub ExcelMacro()
Dim excl As Object
Dim wrbk As Object
Set excl = CreateObject("Excel.Application")
excl.DisplayAlerts = False
Set wrbk = excl.Workbooks.Open("myfile", , True, , "mypassword")
excl.Run "MacroName", "arg1", "arg2"
End Sub
If you use END, Excel will still be running!
Re: Not actually a problem...
Quote:
Originally Posted by WoF
Hello friends.
I want to start a little discussion here about some issues which really intrigued me recently.
Some of you gurus keep going on about how you should Set myObjectVariable = Nothing before leaving a Sub or Function. I never did that and still live. So I made some tests with the following code fragment.
.
As much as I have figured out objects which are created by classes designed of your own in VB are not critical. when writing
Code:
Set myObj = new MyObjClass
then myObj is a pointer pointing to the memory which was allocated for your Object. When the object looses its last reference it is going to garbage automatically so its bad style but works if you aren't setting pointers to nothing at the end of methods. Tested since years in lots of programs, no problem Alos no problem in new languages like C# where it is written down in MS book that this isn't anymore necessary to be done as loosing the last reference an object will be destroyed ( disposed ) automatically. Totally other with resources like e.g. recordsets. In the beginning of my programming experience I often forgot to close streams, recordsets or databaseconnections. I got in heavy troubles with that in a way that suddenly there was 'no more connection possible to the database' errors and such problems more.
So a) never forget to use 'close' in DAO, ADO or DE objects. There also be sure to set the objects to nothing after that.
b) You really can get in troubles when not closing (or if needed quitting ) and setting to nothing excel, word or access objects as then you will create conditions where excel is still running, but not on the screen, but you can still see it in the 'control-alt- delete Window' ( system - dont know english name ) And in this caseit could be possible that you are unable to open an other excel object by the program again and you get an error, that the task is still running and cannot be used in the moment, you will ahve to wait until it is out of use, ( but this never happens :D ) until you are using ctl.alt .delete and killing the running excel thread manually,
So if you have it in your programming style, you have maybe some unnecessary lines of code but no troubles ;)
IMHO the basic behind all this is if you have connection to other applicatiions like word or excel then you get in troubles as they are connections to other threads behind the scene. So when not closieng and setting to nothing the other thread is'n t really closed and disconnected from yyour application and new connections fail. This can be seen as in that case the excel thread or word thread.. is still running. ( looking in the ctl-alt-del window )
See you
Jonny
Re: Not actually a problem...
The two primary cases with VB (not .Net) where "=nothing" are imporant are
1) When the declaration of the variable is at an outter scope. For example a member variable that is onely used for initialization, set it to nothing or the referenced object will live as long as your object
2) When there is significant processing later in the same scope. Example
function F() as integer
Code:
Dim o as SomeClass
o = ....
// using o...
o = nothing
// larger amounts of code that does not depend on o
end function
Re: Not actually a problem...
like anyone had already said, you can't dispose (set <object> = nothing) an object declared implicitly (ie., dim gRecordset As New ADO.Recordset). in the following example, you can't dispose the declared object anywhere in the code (not until the application terminates of course :D)
Public gRecordSet As New ADO.Recordset
Re: Not actually a problem...
Right, thank you guys for your input about Set myObj = Nothing
I'd grant you that some of the arguments read here convince me to watch out when using recordsets and database objects which might stay "open".
Also it seems logically, that running applications (word/excel) will stay open. So you sure had to close them explicitly.
Also CPUWizards statement seems likely, when significant processing is still to follow in the same sub. Also granted.
But I wouldn't consider it "bad style" if I don't do a completely useless Set myLocalFSO = Nothing, followed by destroying a couple of other objects used in a sub/function, whereas leaving the procedure will do all that for me automatically. I'd rather consider it "leaving away redundant statements and making use of lovely VB's kindness to produce more readable code". ;)
Ok.
And what about the ominous FSO as New FileSystemObject?
Any experience had, there?
As far as I tried out, there seems to be absolutely no difference if you go
Dim FSO as New FileSystemObject
and
Dim FSO as FileSystemObject
Set FSO = New FileSystemObject
Please take time with any answer... on top of all I seem to have cought a summer-flu and might be off for a couple of days anyway...
Thank you all, so far. :)
Re: Not actually a problem...
Code:
Dim FSO as Object
Set FSO = New FileSystemObject
Consistency. Set them, close, and destroy. Also, if you properly unload your forms, all objects in that form are destroyed when it is. With the above exceptions.
Re: Not actually a problem...
Quote:
Originally Posted by WoF
Dim FSO as New FileSystemObject
and
Dim FSO as FileSystemObject
Set FSO = New FileSystemObject
IMHO there is absolutley no difference both is creating a pointer and allocating memory on the heap to an object. Why should there be any difference ? Is there really one. ?
Re: Not actually a problem...
What about for Office? Don't lock yourself into a version (altho Intellisense is nice). Declare objects, then bind to local version of Office App. Then the version won't matter*.
Re: Not actually a problem...
Quote:
Originally Posted by WoF
Ok.
And what about the ominous FSO as New FileSystemObject?
Any experience had, there?
As far as I tried out, there seems to be absolutely no difference if you go
Dim FSO as New FileSystemObject
and
Dim FSO as FileSystemObject
Set FSO = New FileSystemObject
Please take time with any answer... on top of all I seem to have cought a summer-flu and might be off for a couple of days anyway...
Thank you all, so far. :)
Dim FSO as New FileSystemObject
the object in this kind of declaration will be created/instantiated upon first use of the variable FSO in the code. so there might be a checking (or somekind of overhead) embedded by the vb compiler, such that, the program will use to ensure that the FSO variable has been instantiated everytime you use it in the code... that might be the difference.
Re: Not actually a problem...
Quote:
Originally Posted by dglienna
Might work, but it's bad practice. It would NOT work with Office Apps, and other types of objects.
Code:
Option Explicit
' These are both examples of Late Binding
Public Sub RunAccessMacro(strDB As String, strMacro As String)
'================================================================
'for late binding declare it As Object and use CreateObject() function
Dim AccessDB As Object
Set AccessDB = CreateObject("Access.Application")
With AccessDB
.OpenCurrentDatabase strDB
.DoCmd.RunMacro strMacro, 1
'.Visible = True 'you decide
.CloseCurrentDatabase
End With
Set AccessDB = Nothing
End Sub
Public Sub ExcelMacro()
Dim excl As Object
Dim wrbk As Object
Set excl = CreateObject("Excel.Application")
excl.DisplayAlerts = False
Set wrbk = excl.Workbooks.Open("myfile", , True, , "mypassword")
excl.Run "MacroName", "arg1", "arg2"
End Sub
If you use END, Excel will still be running!
statement END doesn't call UNLOAD event.
Re: Not actually a problem...
I was looking for somathing seemed :
Code:
'form 1
Private Sub Command1_Click()
x(0) = "A"
x(1) = "B"
x(2) = "C"
End Sub
Private Sub Command2_Click()
Form2.Show
End Sub
Private Sub Command3_Click()
Unload Me
End Sub
Private Sub Form_Load()
List1.AddItem x(0) & ""
List1.AddItem x(1) & ""
List1.AddItem x(2) & ""
End Sub
Private Sub Form_Unload(Cancel As Integer)
'erase x
End Sub
Code:
'Form 2
Private Sub Command1_Click()
Form1.Show
End Sub
step by step :
1.- Open form1
2.- click command1,command2(be load form2) an after command3(Unload form1).
3.-On Form2 click command1 (be load form1 again)
now , List1 is showing values of array x
when I unload form1 it doesn't mean what variables are unloaded too.
I still have 'erase X' in unload event if I want to clean array.
Re: Not actually a problem...
Quote:
Originally Posted by Thread1
Dim FSO as New FileSystemObject
the object in this kind of declaration will be created/instantiated upon first use of the variable FSO in the code. so there might be a checking (or somekind of overhead) embedded by the vb compiler, such that, the program will use to ensure that the FSO variable has been instantiated everytime you use it in the code... that might be the difference.
If this was truly the case, I'd have expected differences in performance, but there is absolutely no such difference to be detected. I checked that in extensive long loops, using an FSO to access files and folders, checking the time with a high precision "QueryPerformanceCounter" call. Exactly the same.
Also, as I said already, I can see, where working with Word/Excel objects which pop up the entire application and might bkeep it open...
But to the last observation of hensa:
I noticed this, too, last recently and was also a little perplexed. I would have expected the variables of a form to loose all their contents when the form got unloaded, but it seems not to be the case, indeed.
It seems that a form, once loaded, is kept in a "cache" or something that it is present already when it has to be loaded again. It is as if it was only hidden, but gave a call to the Form_Unload() .
This gave me a headache recently when I didn't know how a form's variable would remember a certain value after been unloaded and then been shown again. Is that behaviour documented, does anybody know?
Re: Not actually a problem...
Quote:
Originally Posted by WoF
....But to the last observation of hensa:
----when I didn't know how a form's variable would remember a certain value after been unloaded and then been shown again. Is that behaviour documented, does anybody know?
I have had troubles with this in programs where the same windows are opened and closed again. This cuased me to very exactly looking for setting all my variables to 0 or other defined standard settings in Form_load(), especially booleans which I'm using for defining different status of the form. And also to set all my objects to nothing in the Form_unload()
That in the end keeps me from such troubles in between.
BTW in between I have some other intersting troubles with an access mdb which was 1997 style( and coded in VBA with lots of code, )changed to Access 2000 and never had problems with closing the mdb now changed to Access 2003 This mdb now is not closing access so when I close the mdb access still runs in the background and I only can get out of troubls when I'm closing MSAccess in the systems threads window directly ( ctl, alt del window ) Running the same mdb in access 2000 I 'm closing the VBA code and also access closes. I think I have the same troubles with objects not set to nothing maybe there. so I think it doesn't what it should do in some specific cases. Maybe this has to do with the transformation of the mdb from 2000 to 2003
Re: Not actually a problem...
I had no problems with Office XP db's. Haven't tried Office 07 yet