I have moved the code to a new form, and recovered some memory after unloading the form. It solved some of the problem.
Printable View
I have moved the code to a new form, and recovered some memory after unloading the form. It solved some of the problem.
In general (and ignoring this may be part of your problem), Forms (and Controls) should only contain sufficient code to allow them to communicate with a NON-UI class.
using C#, but the intent is 100% the same...
This easily allows you to manage the lifetime of the different aspects independantly. For example, once a ListControl is populated, do you need the original list anymore at all????Code:void SomeBody_Click(object sender, EventArg e)
{
m_Something.HandleClick();
}
Something m_Something;
class Something
{
void HandleClick() { //real work goes here }
}
I tried to make a class on an independent class file, to hold the code, but the only way to get free the memory than I know is
At GC.Collect, some 100 Mb of data are freed (¿How is the right writing for "made free"?).Code:myClassInstance = Nothing
GC.Collect
But putting the code on a Form Class, free 150 MB (after the GC.Collect call the total memory footprint is 50 Mb less, and the form takes more memory for himself, which also free at GC.Collect)
It looks like a form have better memory isolation than a simple class.
PD: I know from your advice that I need to learn more about the garbage collector. Its on my to-do list to read about that, altough from your messages, I understand that is not the solution.
1) Stop even thinking about EVER calling GC.Collect. Put all of you money and valuables in a can, and promise that you will set the can on fire the next time you consider it. In 7+ years developing (many) dozens of DotNet code (a few million lines), there has been exactly 1 case I have seen where it was warranted.
2) Stop worrying about the memory footprint in general. Instead measure system performance during actual usage. If the system does not "need" that 100MB of memory, then freeing it is meaningless. The system knows what is appening and will generally adjust properly. If there is a MEASURED need to influence this, you create artifical demand via "Memory Pressure"
3) Learn about object lifetime. Setting a reference variable to "nothing" has NO impact unless the variable itself is going to stay in scope for significantly longer than the actual object it is referencing. Most often this indicates a design issue with the scope of the variable:
Pseudo-Code:
The variable (m_SomeVariable) has a lifetime of the instance of BadSample, but is only meaningful for the duration of Function2. his should (generally) be recorded by passing the variable as a parameter.Code:class BadSample
{
SomeClass m_SomeVariable;// ONLY used to carry state from Func1 to Func2
public void Function1()
{
m_SomeVariable = new SomeClass();
Function2()
}
private void Function2()
{
// Operations that use m_SomeVariable
}
}
Now the scope of the variable is Function1, and the instance of SomeClass will go out of scope immediately and be eligible for GC, without ever seting anything to "Nothing"/"null".Code:class BadSample
{
SomeClass m_SomeVariable;// ONLY used to carry state from Func1 to Func2
public void Function1()
{
SomeClass someVariable = new SomeClass();
Function2(someVariable );
}
private void Function2(SomeClass someVariable)
{
// Operations that use someVariable
}
}
Once each of your "non-UI" classes are properly implemented to minimize object lifetimes. [And this should be measured with a good profiler] utilizing these classes in you UI (again following the principle of lifetime minimization) can be leveraged.
For example:
A click event needs to perform some calculations and update a textbox
1) Write a class for the calculations
2) In the click handler create and initialize an instance of this class as a local variable
3) Invoke the method(s) which perform the calculations
4) Update the textbox with the results
5) Allow the class instance to simply go out of scope.
3)
I am' sure that you know 1,000,000.54 times more than me about it, although when I not write the GC.Collect line, my app start continuously swapping memory to disk.:confused:
(maybe MS changed something on Framework 3.5 or 3.5 SP1 or Visual Studio 2008 SP1)
It start swapping when the used memory reach 900 Mb (virtual memory is even higher). Anyway later my app eats those 100 Mb "recovered", because of bad design:sick:
But I need to solve the memory wasting step by step. This first.
Those said, and being Christmas near, I would hide all the cans from the pyromaniac wizards:)
Your approach is backwards, you are treating a symptom, not addressing the actual problem.
What happened when you put a profiler break right before where you are currently calling GC.Collect....
How big was each of the Heaps?
How many Time had each generation of GC already run?
When was the LAST time the GC had run for each generation?
How many Finalizers have been Executed?
What was the impact of Creating Memory Pressure?
Are the object in GEN2 expected to live for the duration of the process?
These are all relatively simple and quick measurements to make. They will quickly point out the what is necessary to address the underlying CAUSE.
If you make those measurements and post them [please start a new thread "Understanding Memory Utilization" as this is a more general topic] I will be happy to guide you through the analysis.
The profiler is definately useful for the LAST of the above actions [You may find it easier to use Red-Gate's ANTS profiler]
All of the other items (excluding Last Time of GC) can be done directly in the immediate Window while sitting at a breakpoint in the IDE.
Deteriming the time of LAst GC takes about 15 lines of code be added to your program at startup....
AGAIN: Please start a NEW Thread for discussion of this topic.