MORE INFORMATION
If your Visual Basic application loads a very large number of certain
controls, such as ComboBoxes, you may run out of system resources, which
will result in an "out of memory" error (error #7), and may cause Windows
to stop responding. You can monitor system resources with the 16-bit
Windows API function GetFreeSystemResources.
In Windows 95, Windows 98, and Windows Me, GetFreeSystemResources checks the percentage
of free memory in the following five resource heaps:
- The 16-bit User heap (64K).
- The 32-bit User window heap (2MB).
- The 32-bit User menu heap (2MB).
- The 16-bit GDI heap (64K).
- The 32-bit GDI heap (2MB).
First, it finds the lowest of the three User heaps, and the lowest of the
two GDI heaps. The 16-bit, 64K heaps are almost always the lowest.
Next, for each of the two lowest, it divides the percentage free by the
percentage that was free when Windows was started.
Finally, it returns the lowest of the two.
For example, suppose the five heaps had the following percentages free at
the time Windows started:
Heap Percentage Free
============================= ===============
16-bit User heap (64K) 80%
32-bit User window heap (2MB) 99%
32-bit User menu heap (2MB) 99%
16-bit GDI heap (64K) 75%
32-bit GDI heap (2MB) 99%
Later, with some applications running, suppose the free memory in the five
heaps had dropped to these percentages:
Heap Percentage Free
============================= ===============
16-bit User heap (64K) 40%
32-bit User window heap (2MB) 98%
32-bit User menu heap (2MB) 98%
16-bit GDI heap (64K) 25%
32-bit GDI heap (2MB) 98%
GetFreeSystemResources starts by finding the lowest of the three User heaps
(40%), and the lowest of the two GDI heaps (25%). In both cases, the 16-
bit, 64K heap is lowest.
Next, GetFreeSystemResources divides the percentage free by the percentage
that was free when Windows was started. For the User heap, that's 40%/80% =
50%. For the GDI heap, it calculates 25%/75% = 33%.
Finally, it returns the lowest of the two, 33%.
Note, this behavior is different than GetFreeSystemResources in Windows 3.1
in two ways:
- The three 2MB heaps did not exist in Windows 3.1.
- It did not divide the percentage free from the percentage that was free
at the time Windows started. As a result, it returned a lower
percentage. In the example above, GetFreeSystemResources in Windows 3.1
would have returned 25% instead of 33%.
There is no 32-bit version of GetFreeSystemResources. In Windows 95, 98, Me, NT, and 2000, GetFreeSystemResources has been replaced by GlobalMemoryStatus, which returns the amount of free global memory. Because Windows 95, 98, Me, NT, and 2000 handle system resources more efficiently than Windows 3.x, system resources are usually less of a concern and free global memory is usually more relevant. GlobalMemoryStatus is sometimes confused as being equivalent to GetFreeSystemResources, but in fact it is designed to return entirely different information. While GetFreeSystemResources returns the free percentage of the GDI and User heaps, GlobalMemoryStatus returns the amount of free global memory. In Windows 3.x, 95, 98, and Me, Windows allocates a fixed amount of memory to each of the GDI and User heaps at startup, and can never allocate any more to them no matter how much global memory is free. As a result, it is possible to run out of free system resources while there is still abundant free memory. Because GlobalMemoryStatus does not return information about the GDI and User heaps, it is not appropriate to use GlobalMemoryStatus to monitor these system resources.
To determine free system resources in a 32-bit Visual Basic application,
you must create and call a 16-Bit application that calls
GetFreeSystemResources and exposes the information to other applications.
Note that Windows NT (all versions) and Windows 2000 is designed to dynamically allocate memory to the GDI and User heaps as needed. GetFreeSystemResources always returns 90% on Windows NT and 2000. Unlike other versions of Windows, Windows NT and 2000 do not run out of system resources and stop responding. It is highly unlikely that your Visual Basic application will have any need to monitor system resources on Windows NT and 2000.
Also note that Windows 95, 98, and Me manage system resources considerably more
efficiently than Windows 3.x. Many items formerly stored in the 64K User
and GDI heaps in Windows 3.x are now stored in the three 2MB heaps in
Windows 95 and 98. See the REFERENCES section below for more information.
The following steps show how to create a 16-bit Visual Basic 4.0 OLE server
that determines free system resources and provides that information to OLE
clients, and to call the 16-bit OLE server from a 32-bit version of Visual
Basic and get free system resources from it.
Note, the OLE Server must be created with 16-bit Visual Basic 4.0; it
cannot be created with Visual Basic 5.0 or later, or with 32-bit Visual
Basic 4.0.
If you do not have Visual Basic 4.0, but do have Visual Basic 1.0 for
Windows, 2.0, or 3.0, you can use DDE (Dynamic Data Exchange) rather than
OLE to provide the information to 32-bit applications. In Visual Basic 3.0,
see chapter 21 in the Visual Basic Programmer's Guide, "Communicating with
Other Applications."
If you are a C programmer, you can create a "flat thunking" DLL to provide
the information on Windows 95, 98, and Me. You cannot do flat thunking directly
in Visual Basic, because it requires calling functions given only pointers
to their addresses in memory. See the REFERENCES section below for where to
find more information.
Step-by-Step Example
- Start 16-bit Visual Basic 4.0. Note this will not work with 32-bit
Visual Basic 4.0, or with Visual Basic 5.0 or later.
- Create a new project. Form1 is added by default.
- Choose Module from the Insert menu to add a standard module, and add
the following code to it:
Declare Function GetFreeSystemResources Lib "User" _
(ByVal fuSysResource As Integer) As Integer
Const GFSR_SYSTEMRESOURCES = &H0
Sub Main()
'Stub only.
End Sub
- Choose Class Module from the Insert menu to add a class module, and add the following code to it:
Public Function SystemResources()
SystemResources = GetFreeSystemResources _
(GFSR_SYSTEMRESOURCES)
End Function
- Change the Name property of the class module to clsSR.
- Change the Instancing property of the class module to Createable
SingleUse.
- Change the Public property of the class module to True.
- Alternate click on Form1 in the Project window, and choose "Remove File"
to remove the default form.
- Choose Options from the Tools menu, and select the Project tab. Change
the project name to prjSR, and then change StartMode to "OLE Server."
- From the File menu, save the project, and make the EXE.
- Start a 32-bit version of Visual Basic, such as Visual Basic 4.0
32-bit, or version 5.0 or later.
- Create a new project. Form1 is added by default.
- Choose References from the Project menu (in 32-bit Visual Basic 4.0,
choose References from the Tools menu), and check prjSR. Click OK.
- Double-click on Form1, and add the following code to the Form_Load
event:
Dim oSR As New prjSR.clsSR
MsgBox oSR.SystemResources & _
"% of system resources are free."
Set oSR = Nothing
- Run the project. The Message Box will show the percentage of free
system resources.